<script lang="ts">
  /**
   * Shows all questions for which the answers are unknown.
   * The questions can either be shown all at once or one at a time (in which case they can be skipped)
   */
  import TagRenderingConfig from "../../../Models/ThemeConfig/TagRenderingConfig"
  import { ImmutableStore, Store, UIEventSource } from "../../../Logic/UIEventSource"
  import type { Feature } from "geojson"
  import type { SpecialVisualizationState } from "../../SpecialVisualization"
  import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
  import Tr from "../../Base/Tr.svelte"
  import Translations from "../../i18n/Translations.js"
  import { Utils } from "../../../Utils"
  import { onDestroy } from "svelte"
  import TagRenderingQuestionDynamic from "./TagRenderingQuestionDynamic.svelte"
  import LoginToggle from "../../Base/LoginToggle.svelte"

  export let layer: LayerConfig
  export let tags: UIEventSource<Record<string, string>>
  export let selectedElement: Feature
  export let state: SpecialVisualizationState

  /**
   * If set, only questions for these labels will be shown
   */
  export let onlyForLabels: string[] | undefined = undefined
  const _onlyForLabels = new Set(onlyForLabels)
  /**
   * If set, only questions _not_ having these labels will be shown.
   * This is used for a partial questionbox. If both 'onlyFor' and 'notFor' are set, questions must accept both
   */
  export let notForLabels: string[] | undefined = undefined
  const _notForLabels = new Set(notForLabels)
  export let showAllQuestionsAtOnce: Store<boolean> =
    state.userRelatedState?.showAllQuestionsAtOnce ?? new ImmutableStore(false)

  function allowed(labels: string[]) {
    if (onlyForLabels?.length > 0 && !labels.some((l) => _onlyForLabels.has(l))) {
      return false
    }
    if (notForLabels?.length > 0 && labels.some((l) => _notForLabels.has(l))) {
      return false
    }
    return true
  }

  let baseQuestions = (layer?.tagRenderings ?? [])?.filter(
    (tr) => allowed(tr.labels) && tr.question !== undefined
  )

  /**
   * Ids of skipped questions
   */
  let skippedQuestions = new UIEventSource<Set<string>>(new Set<string>())
  let layerDisabledForTheme = state.userRelatedState.getThemeDisabled(state.theme.id, layer.id)
  layerDisabledForTheme.addCallbackAndRunD((disabled) => {
    console.log("Disabled questions are ", disabled)
    skippedQuestions.set(new Set(disabled.concat(Array.from(skippedQuestions.data))))
  })
  let questionboxElem: HTMLDivElement
  let questionsToAsk = tags.map(
    (tags) => {
      const questionsToAsk: TagRenderingConfig[] = []
      for (const baseQuestion of baseQuestions) {
        if (skippedQuestions.data.has(baseQuestion.id)) {
          continue
        }
        if (
          baseQuestion.condition !== undefined &&
          !baseQuestion.condition.matchesProperties(tags)
        ) {
          continue
        }
        if (baseQuestion.IsKnown(tags)) {
          continue
        }
        questionsToAsk.push(baseQuestion)
      }
      return questionsToAsk
    },
    [skippedQuestions]
  )
  let firstQuestion: UIEventSource<TagRenderingConfig> = new UIEventSource<TagRenderingConfig>(
    undefined
  )
  let allQuestionsToAsk: UIEventSource<TagRenderingConfig[]> = new UIEventSource<
    TagRenderingConfig[]
  >([])

  async function calculateQuestions() {
    const qta = questionsToAsk.data
    firstQuestion.setData(undefined)
    //allQuestionsToAsk.setData([])
    await Utils.awaitAnimationFrame()
    firstQuestion.setData(qta[0])
    allQuestionsToAsk.setData(qta)
  }

  onDestroy(questionsToAsk.addCallback(() => calculateQuestions()))
  onDestroy(showAllQuestionsAtOnce.addCallback(() => calculateQuestions()))
  calculateQuestions()

  let answered: number = 0
  let skipped: number = 0

  let loginEnabled = state.featureSwitches.featureSwitchEnableLogin
  let debug = state.featureSwitches.featureSwitchIsDebugging

  function skip(question: { id: string }, didAnswer: boolean = false) {
    skippedQuestions.data.add(question.id) // Must use ID, the config object might be a copy of the original
    skippedQuestions.ping()
    if (didAnswer) {
      answered++
    } else {
      skipped++
    }
    window.setTimeout(() => {
      Utils.scrollIntoView(questionboxElem)
    }, 50)
  }
</script>

{#if $loginEnabled}
  <div
    bind:this={questionboxElem}
    aria-live="polite"
    class="marker-questionbox-root"
    class:hidden={$questionsToAsk.length === 0 && skipped === 0 && answered === 0}
  >
    {#if $showAllQuestionsAtOnce}
      <div class="flex flex-col gap-y-1">
        {#each $allQuestionsToAsk as question (question.id)}
          <TagRenderingQuestionDynamic config={question} {tags} {selectedElement} {state} {layer} />
        {/each}
      </div>
    {:else if $firstQuestion !== undefined}
      <TagRenderingQuestionDynamic
        config={$firstQuestion}
        {layer}
        {selectedElement}
        {state}
        {tags}
        on:saved={() => {
          skip($firstQuestion, true)
        }}
      >
        <button
          class="secondary"
          on:click={() => {
            skip($firstQuestion)
          }}
          slot="cancel"
        >
          <Tr t={Translations.t.general.skip} />
        </button>
      </TagRenderingQuestionDynamic>
    {/if}

    <LoginToggle {state}>
      <span slot="not-logged-in" />
      {#if $allQuestionsToAsk.length === 0}
        <div class="thanks">
          <Tr t={Translations.t.general.questionBox.done} />
        </div>
      {/if}

      <div class="mb-8 mt-4">
        {#if skipped + answered > 0}
          <div class="flex justify-center">
            {#if answered === 0}
              {#if skipped === 1}
                <Tr t={Translations.t.general.questionBox.skippedOne} />
              {:else}
                <Tr t={Translations.t.general.questionBox.skippedMultiple.Subs({ skipped })} />
              {/if}
            {:else if answered === 1}
              {#if skipped === 0}
                <Tr t={Translations.t.general.questionBox.answeredOne} />
              {:else if skipped === 1}
                <Tr t={Translations.t.general.questionBox.answeredOneSkippedOne} />
              {:else}
                <Tr
                  t={Translations.t.general.questionBox.answeredOneSkippedMultiple.Subs({
                    skipped,
                  })}
                />
              {/if}
            {:else if skipped === 0}
              <Tr t={Translations.t.general.questionBox.answeredMultiple.Subs({ answered })} />
            {:else if skipped === 1}
              <Tr
                t={Translations.t.general.questionBox.answeredMultipleSkippedOne.Subs({ answered })}
              />
            {:else}
              <Tr
                t={Translations.t.general.questionBox.answeredMultipleSkippedMultiple.Subs({
                  answered,
                  skipped,
                })}
              />
            {/if}
          </div>

          {#if skipped + $skippedQuestions.size > 0}
            <button
              class="w-full"
              on:click={() => {
                skippedQuestions.setData(new Set())
                skipped = 0
              }}
            >
              <Tr t={Translations.t.general.questionBox.reactivate} />
            </button>
          {/if}
        {/if}

        {#if $skippedQuestions.size - skipped > 0}
          <button
            class="w-full"
            on:click={() => {
              skippedQuestions.setData(new Set())
              skipped = 0
            }}
          >
            Show the disabled questions for this object
          </button>
        {/if}
        {#if $debug}
          <span class="subtle">
            DBG:Skipped questions are {Array.from($skippedQuestions).join(", ")}
          </span>
        {/if}
      </div>
    </LoginToggle>
  </div>
{/if}
