<script lang="ts">
  /**
   * A special visualisation element which allows to create a full copy (including all tags) of a node
   */

  import Popup from "../../Base/Popup.svelte"
  import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
  import { UIEventSource } from "../../../Logic/UIEventSource"
  import type { Feature } from "geojson"
  import NewPointLocationInput from "../../BigComponents/NewPointLocationInput.svelte"
  import NextButton from "../../Base/NextButton.svelte"
  import { GeoOperations } from "../../../Logic/GeoOperations"
  import type { WayId } from "../../../Models/OsmFeature"
  import { Tag } from "../../../Logic/Tags/Tag"
  import { twJoin } from "tailwind-merge"
  import Translations from "../../i18n/Translations"
  import OpenBackgroundSelectorButton from "../../BigComponents/OpenBackgroundSelectorButton.svelte"
  import Tr from "../../Base/Tr.svelte"
  import ThemeViewState from "../../../Models/ThemeViewState"
  import TagExplanation from "../TagExplanation.svelte"
  import { And } from "../../../Logic/Tags/And"
  import Loading from "../../Base/Loading.svelte"
  import CreateNewNodeAction from "../../../Logic/Osm/Actions/CreateNewNodeAction"
  import DocumentDuplicate from "@babeard/svelte-heroicons/solid/DocumentDuplicate"

  export let state: ThemeViewState
  export let layer: LayerConfig

  export let tags: UIEventSource<Record<string, string>>
  export let feature: Feature
  let c = GeoOperations.centerpointCoordinates(feature)
  let coordinate: { lon: number; lat: number } = { lat: c[1], lon: c[0] }
  let preciseCoordinate: UIEventSource<{ lon: number; lat: number }> = new UIEventSource(undefined)

  let snappedToObject: UIEventSource<WayId> = new UIEventSource<WayId>(undefined)

  // Small helper variable: if the map is tapped, we should let the 'Next'-button grab some attention as users have to click _that_ to continue, not the map
  let preciseInputIsTapped = false

  const forbiddenKeys = new Set(["id", "timestamp", "user", "changeset", "version", "uid"])
  let asTags = tags.map(tgs => Object.keys(tgs).filter(k => !k.startsWith("_") && !forbiddenKeys.has(k)).map(k => new Tag(k, tgs[k])))
  let showPopup: UIEventSource<boolean> = new UIEventSource(false)

  const showTags = state.userRelatedState.showTagsB
  const loggedIn = state.userRelatedState.osmConnection.isLoggedIn
  let creatingCopy = new UIEventSource(false)

  const t = Translations.t.copy

  async function createCopy() {
    creatingCopy.set(true)
    const tags: Tag[] = asTags.data
    const location: { lon: number; lat: number } = preciseCoordinate.data
    const newElementAction = new CreateNewNodeAction(
      tags, location.lat, location.lon, {
        theme: state.theme?.id ?? "unkown",
        changeType: "copy",
      })
    await state.changes.applyAction(newElementAction)
    state.newFeatures.features.ping()
    // The 'changes' should have created a new point, which added this into the 'featureProperties'
    const newId = newElementAction.newElementId
    console.log("Applied pending changes, fetching store for", newId)
    const tagsStore = state.featureProperties.getStore(newId)
    if (!tagsStore) {
      console.error("Bug: no tagsStore found for", newId)
    }
    {
      // Set some metainfo
      const properties = tagsStore.data
      properties["_backend"] = state.osmConnection.Backend()
      properties["_last_edit:timestamp"] = new Date().toISOString()
      const userdetails = state.osmConnection.userDetails.data
      properties["_last_edit:contributor"] = userdetails.name
      properties["_last_edit:uid"] = "" + userdetails.uid
      tagsStore.ping()
    }
    const feature = state.indexedFeatures.featuresById.data.get(newId)
    console.log("Selecting feature", feature, "and opening their popup")
    creatingCopy.set(false)
    showPopup.set(false)
    state.selectedElement.setData(feature)
    tagsStore.ping()
    state.mapProperties.location.setData(location)

  }
</script>

<Popup shown={showPopup} fullscreen>
  <Tr slot="header" t={t.title} />

  {#if $creatingCopy}
    <div class="h-full flex flex-col justify-center">
      <div class="h-fit flex justify-center">
        <Loading>
          <Tr t={t.loading} />

        </Loading>
      </div>
    </div>
  {:else}

    <div class="h-full flex flex-col gap-y-4 justify-between pb-4">
      <Tr t={t.intro} />

      <div class="relative" style="height: calc(100% - 7rem);">
        <NewPointLocationInput
          on:click={() => {
                preciseInputIsTapped = true
              }}
          value={preciseCoordinate}
          snappedTo={snappedToObject}
          {state}
          {coordinate}
          targetLayer={layer}
          presetProperties={$asTags}
        />
        <div
          class={twJoin(
              !preciseInputIsTapped && "hidden",
              "absolute top-0 flex w-full justify-center p-12"
            )}
        >
          <!-- This is an _extra_ button that appears when the map is tapped - see usertest 2023-01-07 -->
          <NextButton on:click={() => createCopy()} clss="primary w-fit">
            <div class="flex w-full justify-end gap-x-2">
              <Tr t={t.confirm} />

            </div>
          </NextButton>
        </div>
        <div class="absolute bottom-0 left-0 p-4">
          <OpenBackgroundSelectorButton {state} />
        </div>
      </div>

      <div class="flex w-full justify-end">
        <NextButton clss="primary sm:shrink-0" on:click={() => createCopy()}>
          <DocumentDuplicate class="w-8 mx-2" />
          <Tr t={t.confirm} />

        </NextButton>
      </div>
      {#if showTags}
        <div class="subtle">
          <TagExplanation tagsFilter={new And($asTags)} linkToWiki />
        </div>
      {/if}
    </div>
  {/if}

</Popup>

{#if $loggedIn}
  <div class="flex justify-end">
    <button on:click={() => showPopup.set(true)}>
      <DocumentDuplicate class="w-4" />
      <Tr t={t.button} />
    </button>
  </div>
{/if}
