<script lang="ts" setup>
import {getRootBarrier} from './utils'
import {dispatch} from '../worker'
import {emit} from '../../shared'
import {computed, nextTick, onMounted, ref, watch} from 'vue'
import {store} from '../store'
import UiDialog from './UiDialog.vue'
import {controller} from './UiDirectoryNamingController'
import {toast} from './UiToastController'

const barrier = ref<Node | null>()
const hasError = ref(false)
const conformClicked = ref(false)
const isSubmitting = ref(false)
const content = ref('')

const title = computed(() => {
  if (controller.action === 'rename') {
    return '重命名文件夹'
  } else if (controller.pid) {
    return "创建子文件夹"
  } else {
    return "创建文件夹"
  }
})

const parent = computed(() => {
  return controller.pid
    ? store.directories.get(controller.pid)
    : undefined
})

const directory = computed(() => {
  return controller.id
    ? store.directories.get(controller.id)
    : undefined
})

const handleCancel = (): void => {
  if (!isSubmitting.value) {
    controller.visible = false
    nextTick(() => {
      hasError.value = false
      conformClicked.value = false
      isSubmitting.value = false
      content.value = ''
    })
  }
}

const handleConfirm = (): void => {
  if (isSubmitting.value) {
    return;
  }
  if (content.value.trim().length < 2) {
    hasError.value = true
  }
  if (hasError.value) {
    return;
  }
  if (!conformClicked.value) {
    conformClicked.value = true
    return
  }
  isSubmitting.value = true
  requestAnimationFrame(async () => {
    try {
      const title = content.value.trim()
      switch (controller.action) {
        case "create": {
          const pid = parent.value?.id ?? 0
          const result = await dispatch("dir", "create", {title, pid});
          store.directories.set(result.id, result);
          toast("success", `成功创建文件夹 “${title}”`)
          if (pid && pid === controller.pid) {
            emit("directory:expanded", parent.value!.id)
          }
          break
        }
        case "rename": {
          const dir = store.directories.get(directory.value!.id);
          if (!dir) {
            toast("error", "文件夹不存在")
            break
          }
          const res = await dispatch("dir", "rename", {id: dir.id, title});
          Object.assign(dir, res);
          toast("success", `成功将文件夹 “${directory.value!.title}” 重命名为 “${title}”`)
          break
        }
      }
      isSubmitting.value = false
      handleCancel()
    } catch (err) {
      isSubmitting.value = false
      toast('error', err as any)
    }
  })
}

watch(() => controller.visible, (value) => {
  if (value && controller.action === 'rename') {
    content.value = directory.value?.title ?? ''
  }
})

watch(content, (value) => {
  conformClicked.value = false
  if (value.trim().length > 1) {
    hasError.value = false
  }
})

onMounted(() => {
  barrier.value = getRootBarrier()
})
</script>

<template>
  <UiDialog
    v-if="barrier"
    :barrier="barrier"
    :visible="controller.visible"
    class="w-96 rounded-md overflow-hidden shadow-2xl"
    outside="shake"
    @dismissed="handleCancel"
  >
    <div class="bg-white p-6">
      <h3
        id="modal-title"
        class="text-base font-semibold leading-6 text-gray-900"
        v-text="title"
      />
      <p class="text-xs text-gray-500 mt-1">
        <template v-if="controller.action === 'rename'">
          您正在修改文件夹 “<b
          class="text-black align-baseline text-sm">{{ directory!.title }}</b>”；<br/>
        </template>
        <template v-else-if="controller.pid">
          您正在为 “<b
          class="text-black align-baseline text-sm">{{ parent!.title }}</b>”
          创建子文件夹；<br/>
        </template>
        <span :class="{ 'text-red-500': hasError }">
          文件夹的名称至少 2 个字符，请尽量不要超过 8 个汉字。
        </span>
      </p>
      <div class="mt-4">
        <input
          v-model="content"
          :disabled="isSubmitting" autocomplete="off"
          class="block w-full rounded-md border-0 px-4 py-2 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6 disabled:bg-gray-100 disabled:cursor-progress"
          maxlength="20" minlength="2"
          placeholder="请输入文件夹名称" required
          @blur="hasError = content.length < 2"/>
      </div>
    </div>
    <div
      class="bg-gray-50 px-6 py-3 flex justify-end gap-4 border-t border-t-slate-200 text-sm font-semibold">
      <button
        :disabled="isSubmitting"
        class="rounded-md px-4 py-2 select-none transition-all bg-white text-gray-900 shadow-sm hover:bg-gray-50 ring-1 ring-inset ring-gray-300 disabled:bg-gray-100 disabled:hover:bg-gray-100 disabled:cursor-progress"
        type="button"
        @click="handleCancel"
      >
        取消
      </button>
      <button
        :disabled="isSubmitting"
        class="inline-flex items-center gap-2 px-4 py-2 rounded-md transition-all select-none bg-indigo-600 text-white shadow-sm hover:bg-indigo-500 disabled:bg-indigo-400 disabled:hover:bg-indigo-400 disabled:cursor-progress"
        type="button"
        @click="handleConfirm"
      >
        <svg
          v-if="isSubmitting"
          class="animate-spin h-3 w-3 text-white"
          fill="none"
          viewBox="0 0 24 24"
          xmlns="http://www.w3.org/2000/svg"
        >
          <circle
            class="opacity-25"
            cx="12"
            cy="12"
            r="10"
            stroke="currentColor"
            stroke-width="4"
          />
          <path
            class="opacity-75"
            d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
            fill="currentColor"
          />
        </svg>
        {{ conformClicked ? "确定提交？" : "提交" }}
      </button>
    </div>
  </UiDialog>
</template>
