<script lang="ts">
  import { onMount, tick } from 'svelte'
  import { shorten, getLangFromUrl } from '$lib/utils'
  import type { Editor } from 'codemirror'
  import { shareUrl, selectedLang } from '../store'
  import ComboBox from './ComboBox.svelte'
  import Icon from '@iconify/svelte'
  import { goto } from '$app/navigation'

  type Language = {
    text: string
    value: string
    data: { mime: string; mode: string }
  }

  let cssClass = ''
  export { cssClass as class }
  export let editor: Editor | null = null
  export let updateShareUrl: () => Promise<void>

  let languages: Language[] = []
  let selectedLanguage: Language | null = null
  let textWrap = false

  let urlInput: HTMLInputElement
  let isUrlInputVisible = false

  onMount(() => {
    $selectedLang = getLangFromUrl()
    selectedLanguage = languages.find((e) => e.value === $selectedLang)!
  })

  selectedLang.subscribe((lang) => {
    textWrap = lang === 'plt' || lang === 'md'
  })

  $: {
    if (editor) {
      // Line wrapping
      editor.setOption('lineWrapping', textWrap)
    }
  }

  $: {
    if (editor) {
      languages = CodeMirror.modeInfo
        .map((e: any) => ({
          text: e.name,
          value: shorten(e.name),
          data: { mime: e.mime, mode: e.mode },
        }))
        .filter((l: any) => l.value !== 'gflm') // Remove github flavored markdown, redundant with markdown

      selectedLanguage =
        selectedLanguage ??
        languages.find((e) => e.value === $selectedLang) ??
        languages.find((e) => e.value === 'plt')!

      const langData = selectedLanguage?.data ?? { mime: null, mode: null }
      // @ts-ignore
      editor.setOption('mode', langData.mime)
      CodeMirror.autoLoadMode(editor, langData.mode)
      $selectedLang = selectedLanguage?.value ?? 'plt'
    }
  }

  async function showUrlInput() {
    // Make sure the url is up to date
    await updateShareUrl()
    isUrlInputVisible = true
    await tick()
    urlInput.value = $shareUrl
    urlInput.select()
  }

  async function showMarkdownLink() {
    await updateShareUrl()
    isUrlInputVisible = true
    await tick()
    urlInput.value = `[Paste snippet](${$shareUrl})`
    urlInput.select()
  }

  async function showIframeCode() {
    await updateShareUrl()
    isUrlInputVisible = true
    await tick()
    // @ts-ignore
    const height = Math.min(editor['doc'].height * 1.1 + 45, 500)
    urlInput.value = `<iframe width="100%" height="${height}" frameborder="0" src="${$shareUrl}"></iframe>`
    urlInput.select()
  }

  async function copyUrl() {
    urlInput.select()
    await navigator.clipboard.writeText(urlInput.value)
    setTimeout(closeUrlInput, 500)
  }

  function closeUrlInput() {
    isUrlInputVisible = false
  }

  async function goToPreview() {
    await updateShareUrl()
    goto($shareUrl)
  }
</script>

<div class={cssClass}>
  {#if isUrlInputVisible}
    <div class="flex gap-2 grow">
      <input
        bind:this={urlInput}
        type="text"
        class="border border-gray-300 bg-transparent p-1 grow"
      />
      <button class="button" on:click={copyUrl} title="Copy">
        <Icon class="text-xl" icon="fluent:copy-16-regular" />
      </button>
      <button class="button" on:click={closeUrlInput} title="Close">
        <Icon class="text-xl" icon="material-symbols:close" />
      </button>
    </div>
  {:else}
    <div class="flex justify-end gap-2">
      <div>
        <ComboBox
          items={languages}
          bind:value={selectedLanguage}
          class="bg-gray-700 border border-gray-300 p-1"
        />
      </div>

      <!-- Toggle text wrap -->
      <button class="button" title="Toggle text wrap" on:click={() => (textWrap = !textWrap)}>
        {#if textWrap}
          <Icon class="text-xl" icon="fluent:text-wrap-24-filled" />
        {:else}
          <Icon class="text-xl" icon="fluent:text-wrap-off-24-filled" />
        {/if}
      </button>

      <!-- Show link input -->
      <button class="button" on:click={showUrlInput} title="Get sharing link">
        <Icon class="text-xl" icon="ph:link-bold" />
      </button>

      <!-- Show markdown link -->
      <button class="button" on:click={showMarkdownLink} title="Get markdown link">
        <Icon class="text-xl" icon="simple-icons:markdown" />
      </button>

      <!-- Show HTML iframe -->
      <button class="button" on:click={showIframeCode} title="Get iframe code">
        <Icon class="text-xl" icon="fluent:code-24-regular" />
      </button>

      <!-- Switch to readonly view -->
      <button class="button" on:click={goToPreview} title="Switch to read-only view">
        <Icon class="text-xl" icon="fluent:eye-12-regular" />
      </button>
    </div>
  {/if}
</div>

<style lang="scss">
  .button {
    @apply text-sm border border-gray-300 p-1 hover:bg-gray-600/50;
  }
</style>
