<script lang="ts">


  import NextButton from "./Base/NextButton.svelte";
  import { UIEventSource } from "../Logic/UIEventSource";
  import ValidatedInput from "./InputElement/ValidatedInput.svelte";
  import EditLayerState from "./Studio/EditLayerState";
  import EditLayer from "./Studio/EditLayer.svelte";
  import Loading from "../assets/svg/Loading.svelte";
  import Marker from "./Map/Marker.svelte";
  import { AllSharedLayers } from "../Customizations/AllSharedLayers";
  import StudioServer from "./Studio/StudioServer";
  import LoginToggle from "./Base/LoginToggle.svelte";
  import { OsmConnection } from "../Logic/Osm/OsmConnection";
  import { QueryParameters } from "../Logic/Web/QueryParameters";

  import layerSchemaRaw from "../../src/assets/schemas/layerconfigmeta.json";
  import If from "./Base/If.svelte";

  export let studioUrl = window.location.hostname === "127.0.0.1" ? "http://127.0.0.1:1235" : "https://studio.mapcomplete.org"; 
  const studio = new StudioServer(studioUrl);
  let layersWithErr = UIEventSource.FromPromiseWithErr(studio.fetchLayerOverview());
  let layers = layersWithErr.mapD(l => l.success);
  let state: undefined | "edit_layer" | "new_layer" | "edit_theme" | "new_theme" | "editing_layer" | "loading" = undefined;

  let initialLayerConfig: { id: string };
  let newLayerId = new UIEventSource<string>("");
  /**
   * Also used in the input field as 'feedback', hence not a mappedStore as it must be writable
   */
  let layerIdFeedback = new UIEventSource<string>(undefined);
  newLayerId.addCallbackD(layerId => {
    if (layerId === "") {
      return;
    }
    if (layers.data?.has(layerId)) {
      layerIdFeedback.setData("This id is already used");
    }
  }, [layers]);


  const layerSchema: ConfigMeta[] = <any>layerSchemaRaw;

  let editLayerState = new EditLayerState(layerSchema, studio);

  function fetchIconDescription(layerId): any {
    return AllSharedLayers.getSharedLayersConfigs().get(layerId)?._layerIcon;
  }

  async function createNewLayer() {
    if(layerIdFeedback.data !== undefined){
      console.warn("There is still some feedback - not starting to create a new layer")
      return
    }
    state = "loading";
    const id = newLayerId.data;
    const createdBy = osmConnection.userDetails.data.name;


    try {

      const loaded = await studio.fetchLayer(id);
      initialLayerConfig = loaded ?? {
        id, credits: createdBy,
        minzoom: 15,
        pointRendering: [
          {
            location: ["point", "centroid"],
            marker: [{
              icon: "circle",
              color: "white"
            }]
          }
        ],
        lineRendering: [{
          width: 1,
          color: "blue"
        }]
      };
    } catch (e) {
      initialLayerConfig = { id, credits: createdBy };
    }
    state = "editing_layer";
  }

  let osmConnection = new OsmConnection(new OsmConnection({
    oauth_token: QueryParameters.GetQueryParameter(
      "oauth_token",
      undefined,
      "Used to complete the login"
    )
  }));

</script>

<If condition={layersWithErr.map(d => d?.error !== undefined)}>
  <div>
    <div class="alert">
      Something went wrong while contacting the MapComplete Studio Server: {$layersWithErr["error"]}
    </div>
    The server might be offline. Please:
    <ul>

      <li>
        Try again in a few minutes
      </li>
      <li>
        Contact <a href="https://app.element.io/#/room/#MapComplete:matrix.org">the MapComplete community via the
        chat.</a> Someone might be able to help you
      </li>
      <li>
        File <a href="https://github.com/pietervdvn/MapComplete/issues">an issue</a>
      </li>
      <li>
        Contact the devs via <a href="mailto:info@posteo.net">email</a>
      </li>
    </ul>
  </div>
  <LoginToggle ignoreLoading={true} slot="else" state={{osmConnection}}>
    <div slot="not-logged-in">
      <NextButton clss="primary" on:click={() => osmConnection.AttemptLogin()}>
        Please log in to use MapComplete Studio
      </NextButton>
    </div>
    {#if state === undefined}
      <h1>MapComplete Studio</h1>
      <div class="w-full flex flex-col">

        <NextButton on:click={() => state = "edit_layer"}>
          Edit an existing layer
        </NextButton>
        <NextButton on:click={() => state = "new_layer"}>
          Create a new layer
        </NextButton>
        <!--
        <NextButton on:click={() => state = "edit_theme"}>
          Edit a theme
        </NextButton>
        <NextButton on:click={() => state = "new_theme"}>
          Create a new theme
        </NextButton>
        -->
      </div>
    {:else if state === "edit_layer"}
      <div class="flex flex-wrap">
        {#each Array.from($layers) as layerId}
          <NextButton clss="small" on:click={async () => {
        state = "loading"
        initialLayerConfig = await studio.fetchLayer(layerId)
        state = "editing_layer"
       }}>
            <div class="w-4 h-4 mr-1">
              <Marker icons={fetchIconDescription(layerId)} />
            </div>
            {layerId}
          </NextButton>
        {/each}
      </div>
    {:else if state === "new_layer"}
      <div class="interactive flex m-2 rounded-2xl flex-col p-2">
        <h3>Enter the ID for the new layer</h3>
        A good ID is:
        <ul>
          <li>a noun</li>
          <li>singular</li>
          <li>describes the object</li>
          <li>in English</li>
        </ul>
        <div class="m-2 p-2 w-full">

          <ValidatedInput type="id" value={newLayerId} feedback={layerIdFeedback} on:submit={() => createNewLayer()} />
        </div>
        {#if $layerIdFeedback !== undefined}
          <div class="alert">
            {$layerIdFeedback}
          </div>
        {:else }
          <NextButton clss="primary" on:click={() => createNewLayer()}>
            Create layer {$newLayerId}
          </NextButton>
        {/if}
      </div>
    {:else if state === "loading"}
      <div class="w-8 h-8">
        <Loading />
      </div>
    {:else if state === "editing_layer"}
      <EditLayer {initialLayerConfig} state={editLayerState} />
    {/if}
  </LoginToggle>
</If>