<script>
  import AutoComplete from "simple-svelte-autocomplete";
  import France from './assets/France.svelte'
  import JSConfetti from 'js-confetti'
  import departements from './assets/départements.json'
  import listDep from './assets/listDeps.json'
	import { onMount } from 'svelte';
  import './rainbow.css';
  import './zoom.css';

  const jsConfetti = new JSConfetti()
  const autoCompleteItems = listDep.map(code => ({
      "code": code,
      "name": departements[code]['name']
    })
  ).sort((a, b) => a.name > b.name ? 1 : -1);

  let france = France;
  let currentDepGuessed = -1;
  let listGuesses = []
  let codeSelected;
  let depSelected = 1;
  let highlightedDep;
  let sendButton;
  let guessNumber = true;

  let winStreak = 0;
  let lossStreak = 0;
  let winCount = 0;
  let guessCount = 0;
  let canImprove = true;
  let feedbackString = "";

  let fr_svg; // France SVG binding
  let info;   // tooltip div binding

  function addClassGuess(dep, className) {
    if(["75", "92", "93", "94"].includes(dep)) {
      addClassGuess(dep + "-bis", className)
    }
    const d = document.getElementById(`dep_${dep}`)
    if(d) d.classList.add(className)
  }
  /* Actually a shame it still doesn't exists in the standard library */
  function shuffleArray(array) {
    for(const i of array.keys()) {
        const j = Math.floor(Math.random() * (array.length - i)) + i;
        [array[i], array[j]] = [array[j], array[i]];
    }
  }
  function removeClassGuess(dep, className) {
    if(["75", "92", "93", "94"].includes(dep)) {
      removeClassGuess(dep + "-bis", className)
    }
    const d = document.getElementById(`dep_${dep}`)
    if(d) d.classList.remove(className)
  }
  function start() {
    winCount = 0;
    guessCount = 0;

    // Disable tooltip.
    info.classList.remove("active") // Should not be active seen the button should have launch mouseleave event.

    // Clean the map of any previous style
    for(let dep of listDep) {
      removeClassGuess(dep, "win")
      removeClassGuess(dep, "miss")
      removeClassGuess(dep, "loss")
      removeClassGuess(dep, "rainbow-fill")
    }

    listGuesses = listDep.slice(0);
    shuffleArray(listGuesses);
    currentDepGuessed = 0;
    addClassGuess(listGuesses[0], 'rainbow-fill')
  }
  function next() {
    if(sendButton) {
      sendButton.focus();
    }
  }

  function validate() {
    guessCount += 1
    if(depSelected === listGuesses[currentDepGuessed] && (!guessNumber || codeSelected == listGuesses[currentDepGuessed])) {
      feedbackString = ` 🎉 Bravo !`
      addClassGuess(listGuesses[currentDepGuessed], 'win')
      winCount += 1
      lossStreak = 0;
      winStreak += 1;
    } else if(depSelected === listGuesses[currentDepGuessed] || (guessNumber && codeSelected == listGuesses[currentDepGuessed]) ) {
      if(depSelected === listGuesses[currentDepGuessed]) {
        feedbackString = `👏 Pas mal ! C'était le numéro ${listGuesses[currentDepGuessed]}`
      } else {
        feedbackString = `👏 Pas mal ! C'était ${departements[listGuesses[currentDepGuessed]]['det']} ${departements[listGuesses[currentDepGuessed]]['name']}`
      }
      addClassGuess(listGuesses[currentDepGuessed], 'miss')
      winStreak = 0;
      lossStreak = 0;
    } else {
      const code = listGuesses[currentDepGuessed];
      feedbackString = `C'était ${departements[listGuesses[currentDepGuessed]]['det']} ${departements[code]['name']} (${code})`
      addClassGuess(listGuesses[currentDepGuessed], 'loss')
      lossStreak += 1;
      winStreak = 0;
    }

    removeClassGuess(listGuesses[currentDepGuessed], 'rainbow-fill')
    currentDepGuessed += 1

    if(currentDepGuessed < listGuesses.length) {
      addClassGuess(listGuesses[currentDepGuessed], 'rainbow-fill')
    } else {
      currentDepGuessed = -1;
      canImprove = winCount != guessCount
    }

    // Ugly but took me 10s to type
    const autocomplete = document.getElementById('autocomplete');
    autocomplete.value = "";
  }

  function replaceSlide({ duration = 200, pixels = 200} = {}) {
    function send(node) {
      return function() {
        let top = node.offsetTop - parseFloat(getComputedStyle(node).marginTop);
        let left = node.offsetLeft;
        return {
          duration,
          css(t, u) {
            // Remove the element from the normal flow so that it doesn't interfere with the
            // placement of the new element, but position it exactly where it was.
            return `position:absolute;top:${top}px;left:${left}px;opacity:${t};transform:translateX(-${Math.floor(pixels*u)}px)`;
          }
        }
      }
    }

    function receive(node) {
      return function() {
        return {
          duration,
          css(t, u) {
            return `transform:translateX(${Math.floor(pixels*u)}px);opacity:${t}`;
          }
        }
      }
    }
    return [send, receive];
  }

	const [send, receive] = replaceSlide();


  function showConfetti() {
      jsConfetti.addConfetti()
  }

  function initTooltip() {
    /**
     * Set the tooltip event listener to show the department name on hover.
     */
    const deps = fr_svg.getElementsByTagName("path");

    function updatePosition(e) {
      if(currentDepGuessed == -1) {
        info.style.top = `${e.pageY - 70}px`;
        info.style.left = `${e.pageX - 0}px`;
      }
    }

    for(let dep of deps) {
      if(dep.id.startsWith("dep_")) {
        const code = dep.id.slice(4).replace("-bis", "");

        dep.addEventListener("mouseenter", e => {
          if(currentDepGuessed == -1) {
            info.classList.add("active")
            info.innerHTML = `<b>${departements[code]['name']}</b> (${code})`
            updatePosition(e)
          }
        });

        dep.addEventListener("mouseleave", () => {
          info.classList.remove("active")
        });
        dep.addEventListener("mousemove", updatePosition);
      }
    }
  }

	onMount(() => {
    initTooltip();
  });

</script>

<main>

  {#if currentDepGuessed == -1}
  <h1>Départements Français</h1>
    <br/>
  {:else}
    <h1>Quel est ce département ?</h1>
  {/if}

  <svelte:component this={france} bind:svg={fr_svg}/>

  {#if currentDepGuessed == -1}
  <div class="response" in:receive out:send>
    {#if guessCount > 0}
      <div>
      <span>{winCount} / {guessCount}</span><br>
      {#if canImprove}
        Tu peux faire mieux !<br>
      {:else}
        👏 Parfait ! 👑<br>
      {/if}
      </div>
    {/if}

    <input type="checkbox" bind:checked={guessNumber} id="noNum"><label for="noNum">Devine les numéros</label><br>
    <button type="button" on:click={start}>{ guessCount > 0 ? "Recommencer" : "Démarrer" }</button>
  </div>
  {:else}
  <div class="response" in:receive out:send>
    {#if guessNumber}
    <select class="guessCode" bind:value={codeSelected}>
      {#each listDep as dep}
      <option value={dep}>
      {dep}
      </option>
      {/each}
    </select>
    {/if}

    <AutoComplete
        items={autoCompleteItems}
        bind:highlightedItem={highlightedDep}
        bind:value={depSelected}
        labelFieldName="name"
        id="autocomplete"
        minCharactersToSearch=2
        valueFieldName="code" onChange={next}/>
  </div>
  <div class="response" in:receive out:send>
      <button bind:this={sendButton} on:click={validate}>Devine !</button>
      <span>{winCount} / {guessCount}</span>
  </div>
  <div class="response" in:receive out:send>
    <div>{feedbackString}</div>
  </div>
  {/if}

  <div class="tooltip" bind:this={info}>Hello</div>
</main>

<style>
  button {
    border: 1px solid black;
  }
  button:hover, button:focus {
    background-color: green;
    color: white;
    border: 1px solid lightgreen;
  }
  .response{
    margin: 5px;

    display: flex;
    align-items: center;
    justify-content: center;
  }
  .response > * {
    margin: 10px;
  }
  .guessCode {
    height: 35px;
    margin: 0;
    margin-right: 5px;
  }
</style>
