<template>
  <q-dialog persistent v-model="show_dialog" @before-hide="resetData">
    <q-card
      class="overflow-hidden"
      style="overflow-y: scroll; max-width: 60vw; max-height: 80vh"
    >
      <q-card-section class="q-ma-none q-pa-sm">
        <div class="row">
          <div class="col-auto text-h6">
            {{ $t("file manage") }}
          </div>
          <q-space />
          <div>
            <q-btn
              :loading="loading"
              flat
              round
              icon="close"
              color="red"
              v-close-popup
            >
              <q-tooltip>
                {{ $t("close") }}
              </q-tooltip>
            </q-btn>
          </div>
        </div>
      </q-card-section>

      <q-separator />
      <div class="row">
        <div class="q-pa-md q-gutter-sm">
          <q-breadcrumbs separator="/">
            <q-breadcrumbs-el
              :disable="status == 'uploading'"
              icon="home"
              to="#"
              @click="path = ''"
            />
            <q-breadcrumbs-el
              v-for="(item, index) of paths.slice(1)"
              :key="index"
              :label="item.name"
              :disable="status == 'uploading'"
              to="#"
              @click="path = item.path"
            />
          </q-breadcrumbs>
        </div>
      </div>
      <q-separator />
      <div class="row">
        <q-btn
          flat
          icon="arrow_back"
          :disable="path.trim() == '' || status == 'uploading'"
          @click="backToParentPath"
          :label="$t('back')"
        >
          <q-tooltip>
            {{ $t("back") }}
          </q-tooltip>
        </q-btn>
        <q-btn
          flat
          icon="arrow_forward"
          :disable="
            prev_path == '' || path == prev_path || status == 'uploading'
          "
          @click="(path = prev_path) && (prev_path = '')"
          :label="$t('forward')"
        >
          <q-tooltip>
            {{ $t("forward") }}
          </q-tooltip>
        </q-btn>
        <q-btn
          flat
          icon="refresh"
          @click="refresh_file_list"
          :disable="status == 'uploading'"
          :label="$t('refresh')"
        >
          <q-tooltip>
            {{ $t("refresh") }}
          </q-tooltip>
        </q-btn>
        <q-btn
          flat
          icon="upload"
          :label="$t('upload file')"
          :disable="status == 'uploading'"
          @click="status = 'uploading'"
        >
          <q-tooltip>
            {{ $t("upload file") }}
          </q-tooltip>
        </q-btn>
        <q-btn
          flat
          icon="block"
          v-if="status == 'uploading'"
          :label="$t('cancel upload file')"
          @click="status = 'normal'"
        >
          <q-tooltip>
            {{ $t("cancel upload file") }}
          </q-tooltip>
        </q-btn>
      </div>
      <q-separator />

      <q-card-section
        style="max-height: 50vh; width: 60vw; max-height: 80vh"
        class="scroll q-pa-none q-ma-none"
      >
        <q-table
          style="height: 69vh"
          v-show="status != 'uploading'"
          :rows="files"
          :columns="columns"
          virtual-scroll
          color="primary"
          row-key="name"
          :loading="loading"
          :rows-per-page-options="[0]"
          :virtual-scroll-sticky-size-start="48"
          @row-contextmenu="onContextMenu"
          @row-dblclick="onTableItemDBClick"
        >
          <template v-slot:loading>
            <q-inner-loading showing color="primary" />
          </template>
          <template v-slot:body-cell="props">
            <q-td :props="props">
              <div v-if="props.col.name == 'name'">
                <q-icon
                  :name="props.row.is_directory ? 'folder' : 'description'"
                  style="color: #ffbe4a; font-size: 2.5em"
                ></q-icon>
                {{
                  props.value.length > 23
                    ? props.value.substr(0, 23) + "..."
                    : props.value
                }}
                <q-tooltip> {{ props.value }} </q-tooltip>
              </div>
              <div v-else-if="props.col.name != 'operator'">
                {{ props.value }}
              </div>
              <div v-else>
                <div v-if="props.row.can_write">
                  <a href="#" @click="(evt) => renameFile(props.row)">
                    {{ $t("rename") }}
                    <q-tooltip> {{ $t("click") }}{{ $t("rename") }} </q-tooltip>
                  </a>
                  &nbsp;&nbsp;&nbsp;&nbsp;
                  <a href="#" @click="(evt) => deleteFile(props.row)">
                    {{ $t("delete") }}
                    <q-tooltip> {{ $t("click") }}{{ $t("delete") }} </q-tooltip>
                  </a>
                </div>
              </div>
            </q-td>
          </template>
        </q-table>
        <div v-show="status == 'uploading'" class="row q-ma-sm">
          <q-space />
          <q-uploader
            :url="getUrl"
            method="post"
            :headers="generatorFileUploadHeaders"
            :label="$t('select file') + ':'"
            accept="*"
            @uploaded="onUploaded"
            @failed="onFailed"
          >
          </q-uploader>
          <q-space />
        </div>
      </q-card-section>
    </q-card>
  </q-dialog>
  <div>
    <q-menu :target="target_dom" v-model="show_context_menu">
      <q-list>
        <q-item
          clickable
          v-close-popup
          @click="(evt) => copyStringToClipboard(current_file.name)"
        >
          <q-item-section avatar><q-icon name="file_copy" /></q-item-section>
          <q-item-section>{{ $t("copy file name") }}</q-item-section>
        </q-item>
        <q-item
          clickable
          v-close-popup
          v-if="current_file && current_file.can_write"
          @click="(evt) => renameFile(current_file)"
        >
          <q-item-section avatar><q-icon name="edit" /></q-item-section>
          <q-item-section>{{ $t("rename") }}</q-item-section>
        </q-item>
        <q-item
          clickable
          v-close-popup
          v-if="current_file && current_file.can_write"
          @click="(evt) => deleteFile(current_file)"
        >
          <q-item-section avatar
            ><q-icon name="delete" color="red"
          /></q-item-section>
          <q-item-section>{{ $t("delete") }}</q-item-section>
        </q-item>
      </q-list>
    </q-menu>
  </div>
</template>

<style scoped>
.disable_tree {
  background: #9e9e9e;
  cursor: wait;
  pointer-events: none;
}

.limit_text_length {
  overflow: auto;
  white-space: nowrap;
  text-overflow: clip;
  max-width: 20vw;
}

a,
a:active,
a:visited,
a:link,
a:focus {
  color: #428bca;
  outline: none;
  background: none;
  text-decoration: none;
}

a:hover {
  outline: none;
  background: none;
  text-decoration: underline;
}
</style>

<script lang="ts">
import { defineComponent, ref, watch, computed } from "vue";
import { useStore } from "src/store";
import { useQuasar, date, copyToClipboard } from "quasar";
import { useI18n } from "vue-i18n";
import { api } from "boot/axios";
import GlobalData from "src/common/GlobalData";
import FileEntity from "src/entities/FileEntity";
import { HttpProtocol } from "src/entities/HttpProtocol";

class _BreadcrumbItem {
  name: string = "";
  path: string = "";

  constructor(name?: string, path?: string) {
    this.name = name ?? "";
    this.path = path ?? "";

    if (this.path == "/" || this.path == "\\") {
      this.path = "";
    }
  }
}

export default defineComponent({
  name: "ComponentFileManageDialog",

  setup() {
    let $store = useStore();
    let $q = useQuasar();
    let $t = useI18n();

    let show_dialog = ref(false);
    let loading = ref(false);
    let files = ref(<FileEntity[]>[]);
    let show_context_menu = ref(false);
    let target_dom: any = ref(document.body.children[0]);
    let current_file = ref(new FileEntity());
    let path = ref("");
    let prev_path = ref("");
    let paths = ref([new _BreadcrumbItem("root", "")]);
    let status = ref("normal");
    let upload_url = ref("");

    const columns = [
      {
        align: "left",
        name: "name",
        required: true,
        label: $t.t("file name"),
        field: "name",
        sortable: true,
      },
      {
        name: "file_size",
        align: "center",
        label: $t.t("file size"),
        field: (val: FileEntity) =>
          val.is_directory ? null : Math.ceil((val ? val.file_size : 0) / 1000),
        format: (val: any) => (val != null ? `${val} KB` : ""),
        sortable: true,
      },
      {
        name: "last_edit_time",
        align: "center",
        label: $t.t("last edit time"),
        field: (val: FileEntity) =>
          date.formatDate(
            new Date((val ? val.last_edit_time : 0) * 1000),
            "YYYY-MM-DD HH:mm:ss"
          ),
        format: (val: any) => `${val}`,
        sortable: true,
      },
      {
        name: "can_read",
        align: "center",
        label: $t.t("can read"),
        field: (val: FileEntity) => val && val.can_read,
        format: (val: any) => `${$t.t(val ? "can true" : "can false")}`,
        sortable: true,
      },
      {
        name: "can_write",
        align: "center",
        label: $t.t("can write"),
        field: (val: FileEntity) => val && val.can_write,
        format: (val: any) => `${$t.t(val ? "can true" : "can false")}`,
        sortable: true,
      },
      {
        name: "can_exec",
        align: "center",
        label: $t.t("can exec"),
        field: (val: FileEntity) => val && val.can_exec,
        format: (val: any) => `${$t.t(val ? "can true" : "can false")}`,
        sortable: true,
      },
      {
        align: "center",
        name: "operator",
        label: $t.t("operator"),
      },
    ];

    const _request_list_files = async (path: string) => {
      loading.value = true;
      let client = GlobalData.getInstance().getCurrentClient();
      if (client) {
        let url = new URL(client.url);
        url.port =
          GlobalData.getInstance().applicationConfig?.httpserver_port ??
          HttpProtocol.DefaultHttpPort.toString();
        url.pathname = HttpProtocol.RequestPathListFile;
        url.protocol = "http:";
        url.searchParams.append("path", path);
        return await api.get(url.toString());
      }
      loading.value = false;
      return null;
    };

    const _show_files = (response: any) => {
      if (response) {
        if (response.status == 200) {
          const file_entity = response.data as FileEntity[];
          if (file_entity) {
            files.value = file_entity;
          } else {
            console.error("data is not typeof FileEntity!", response);
          }
        } else {
          console.warn(response);
        }
      }
      loading.value = false;
    };

    const refresh_file_list_async = async () => {
      const response = await _request_list_files(path.value);
      _show_files(response);
    };

    const refresh_file_list = () => {
      refresh_file_list_async();
    };

    watch(
      () => path.value,
      (newValue: string) => {
        paths.value = [];
        let parent_item = new _BreadcrumbItem("root", "");
        for (let item of newValue.split("/")) {
          let temp = new _BreadcrumbItem(item, parent_item.path + "/" + item);
          paths.value.push(temp);
          parent_item = temp;
        }
        if (paths.value.length < 1) {
          paths.value.push(new _BreadcrumbItem("root", ""));
        }
        refresh_file_list();
      }
    );

    return {
      show_dialog,
      loading,
      files,
      columns,
      show_context_menu,
      path,
      prev_path,
      paths,
      target_dom,
      upload_url,
      current_file,
      refresh_file_list,
      refresh_file_list_async,
      status,
      showDialog() {
        refresh_file_list();
        show_dialog.value = true;

        // let client = GlobalData.getInstance().getCurrentClient();
        // if (client) {
        //   let url = new URL(client.url);
        //   url.port =
        //     GlobalData.getInstance().applicationConfig?.httpserver_port ??
        //     HttpProtocol.DefaultHttpPort.toString();
        //   url.pathname = HttpProtocol.RequestUploadFile;
        //   url.protocol = "http:";
        //   url.searchParams.append("type", HttpProtocol.UploadTypeDatabase);
        //   url.searchParams.append("target_path", path.value);
        //   upload_url.value = url.toString();
        // }
      },
      generatorFileUploadHeaders(files: File[]) {
        if (files.length > 0) {
          return [
            {
              name: HttpProtocol.kHeaderXProductName,
              value: HttpProtocol.kHeaderDefaultValueXProductName,
            },
            {
              name: HttpProtocol.kHeaderXFileLength,
              value: files[0].size,
            },
          ];
        }
        return [];
      },
      resetData() {
        loading.value = false;
        files.value = [];
        path.value = "";
        status.value = "normal";
        upload_url.value = "";
      },
      deleteFile(file: FileEntity) {},
      renameFile(file: FileEntity) {},
      copyStringToClipboard(value: string) {
        copyToClipboard(value);
      },
      onContextMenu(evt: PointerEvent, row: FileEntity, index: number) {
        evt.preventDefault();
        evt.stopPropagation();

        target_dom.value = evt.srcElement;
        current_file.value = row;
        if (row.can_write) {
          show_context_menu.value = true;
        }
      },
      onTableItemDBClick(evt: PointerEvent, row: FileEntity, index: number) {
        if (row && row.is_directory) {
          path.value += "/" + row.name;
        }
      },
      backToParentPath() {
        const pos = path.value.lastIndexOf("/");
        if (pos != -1) {
          prev_path.value = path.value;
          path.value = path.value.substr(0, pos);
        }
      },
      getUrl(file: File[]) {
        let client = GlobalData.getInstance().getCurrentClient();
        if (client) {
          let url = new URL(client.url);
          url.port =
            GlobalData.getInstance().applicationConfig?.httpserver_port ??
            HttpProtocol.DefaultHttpPort.toString();
          url.pathname = HttpProtocol.RequestUploadFile;
          url.protocol = "http:";
          url.searchParams.append("type", HttpProtocol.HttpUploadTypeNormal);
          url.searchParams.append("base_dir", path.value);
          console.log(url.toString());
          return url.toString();
        }
        return "#";
      },
      onUploaded() {
        $q.notify({
          type: "positive",
          message: $t.t("file upload") + $t.t("success") + "!",
          position: "top",
          timeout: 1000,
        });
      },
      onFailed(info: any) {
        console.log(info);
        $q.notify({
          type: "warning",
          message: $t.t("file upload") + $t.t("fail") + "!",
          position: "top",
          timeout: 1000,
        });
        loading.value = false;
      },
    };
  },
});
</script>
