<script lang="ts">
  import type { Editor } from 'codemirror'
  import { onMount } from 'svelte'
  import { debounce } from 'lodash-es'
  import * as brotli from '$lib/brotli'
  import * as lzma from '$lib/lzma'
  import { byId } from '$lib/utils'
  import TopBar from '../components/TopBar.svelte'
  import { selectedLang, shareUrl } from '../store'

  let editor: Editor | null = null
  const readOnly = false

  let charLen = 0
  let compressed: string = ''
  let waiting = false
  let setLanguage: (lang: string) => void

  onMount(async () => {
    initCodeEditor()
    // extract the part in the url after the hash
    const hash = window.location.hash.slice(1)
    if (hash) {
      // decompress the data
      let decompressed: string
      if (hash.startsWith('XQAAA')) {
        decompressed = await lzma.decompress(hash)
      } else {
        decompressed = await brotli.decompress(hash)
      }
      // set the editor value
      if (editor) {
        editor.setValue(decompressed)
      }
    }

    const lang = new URLSearchParams(window.location.search).get('l')
    if (lang) {
      setLanguage(lang)
    }
    else {
      setLanguage('plt')
    }
  })

  async function updateShareUrl() {
    if (editor) {
      const url = new URL(window.location.href)
      compressed = await brotli.compress(editor.getValue())
      if ($selectedLang) {
        url.searchParams.set('l', $selectedLang)
      }
      url.hash = compressed
      $shareUrl = url.toString()
    }
  }

  const updateShareUrlDebounced = debounce(async () => {
    updateShareUrl()
    waiting = false
  }, 1000)

  const initCodeEditor = () => {
    CodeMirror.modeURL = 'https://cdn.jsdelivr.net/npm/codemirror@5.65.5/mode/%N/%N.js'
    editor = new CodeMirror(byId('editor'), {
      lineNumbers: true,
      theme: 'dracula',
      readOnly: readOnly,
      lineWrapping: false,
      scrollbarStyle: 'native',
    }) as Editor

    if (readOnly) {
      document.body.classList.add('readonly')
    }

    editor.on('change', async () => {
      if (editor) {
        waiting = true
        charLen = editor.getValue().length
        updateShareUrlDebounced()
      }
    })
  }
</script>

<div class="flex flex-col font-mono h-screen bg-gray-700">
  <TopBar {editor} {updateShareUrl} bind:setLanguage />

  <div id="editor" class="grow overflow-hidden" />

  {editor?.getValue()}

  <div id="footer" class="p-2 text-sm z-10">
    Data length: {charLen}
    | Link length: {waiting ? '?' : $shareUrl.length}
    ({waiting || !compressed.length || !charLen
      ? '?'
      : Math.round(($shareUrl.length / charLen) * 100)}% of original)
  </div>
</div>

<style>
  :global(div.CodeMirror) {
    height: 100%;
    font-size: 15px;
  }
  #footer {
    --tw-shadow: 0 -4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
    --tw-shadow-colored: 0 -4px 6px -1px var(--tw-shadow-color),
      0 2px 4px -2px var(--tw-shadow-color);
    box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
      var(--tw-shadow);
  }
</style>
