<template>
  <q-dialog
    persistent
    v-model="show_dialog"
    @before-hide="resetData"
    @keydown="
      (evt) => {
        if (!loading && evt.keyCode == 27) {
          show_dialog = false;
        }
      }
    "
  >
    <q-card
      class="overflow-hidden"
      style="overflow-y: scroll; max-width: 70vw; max-height: 85vh"
    >
      <q-card-section class="q-ma-none q-pa-sm">
        <div class="row">
          <div v-if="status == 'select'" class="col-auto text-h6">
            {{ $t("select file") }}({{ filters.join(";") }})
          </div>
          <div v-else class="col-auto text-h6">
            {{ $t("file manage") }}
          </div>
          <q-space />
          <div>
            <q-btn
              :loading="loading"
              :disable="loading"
              no-caps
              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="uploading"
              icon="home"
              :label="default_path_label"
              to="#"
              @click="path = default_path"
            />
            <q-breadcrumbs-el
              v-for="(item, index) of paths.slice(1)"
              :key="index"
              :label="item.name"
              :disable="uploading"
              to="#"
              @click="path = item.path"
            />
          </q-breadcrumbs>
        </div>
      </div>
      <q-separator />
      <div class="row">
        <q-btn-dropdown
          stretch
          flat
          no-caps
          :label="default_path_label"
          :disable="uploading"
        >
          <q-list>
            <q-item
              v-for="(item, index) of disk_options"
              :key="index"
              clickable
              v-close-popup
              @click="default_path = item.value"
            >
              <q-item-section avatar>
                <q-icon
                  :name="item.label == $t('local disk') ? 'desktop_mac' : 'usb'"
                />
              </q-item-section>
              <q-item-section> {{ item.label }} </q-item-section>
            </q-item>
          </q-list>
        </q-btn-dropdown>
        <q-btn
          flat
          icon="arrow_back"
          no-caps
          :disable="path.trim() == '' || uploading"
          @click="backToParentPath"
          :label="$t('back')"
        >
          <q-tooltip>
            {{ $t("back") }}
          </q-tooltip>
        </q-btn>
        <q-btn
          flat
          no-caps
          icon="arrow_forward"
          :disable="prev_path == '' || path == prev_path || uploading"
          @click="(path = prev_path) && (prev_path = '')"
          :label="$t('forward')"
        >
          <q-tooltip>
            {{ $t("forward") }}
          </q-tooltip>
        </q-btn>
        <q-btn
          flat
          icon="refresh"
          no-caps
          @click="refresh_file_list"
          :disable="uploading"
          :label="$t('refresh')"
        >
          <q-tooltip>
            {{ $t("refresh") }}
          </q-tooltip>
        </q-btn>
        <q-btn
          flat
          no-caps
          icon="content_paste"
          @click="pasteFile"
          :disable="
            !(clipboard && clipboard.type && clipboard.type != 'NONE') ||
            path == clipboard.path
          "
          :label="$t('paste')"
        >
          <q-tooltip>
            {{ $t("paste") }}
          </q-tooltip>
        </q-btn>
        <q-btn
          flat
          icon="create_new_folder"
          no-caps
          @click="onCreateNewFolder"
          :disable="loading || uploading"
          :label="$t('create folder')"
        >
          <q-tooltip>
            {{ $t("create folder") }}
          </q-tooltip>
        </q-btn>
        <q-btn
          flat
          v-if="!uploading"
          no-caps
          icon="upload"
          :label="$t('upload file')"
          @click="uploading = true"
        >
          <q-tooltip>
            {{ $t("upload file") }}
          </q-tooltip>
        </q-btn>
        <q-btn
          flat
          icon="block"
          no-caps
          v-if="uploading"
          :label="$t('cancel upload file')"
          @click="uploading = false"
        >
          <q-tooltip>
            {{ $t("cancel upload file") }}
          </q-tooltip>
        </q-btn>
      </div>
      <q-separator />

      <q-card-section
        style="width: 70vw; max-height: 85vh"
        class="scroll q-pa-none q-ma-none"
      >
        {{}}
        <q-table
          :style="{
            height:
              ($q.platform.is.ipad && $store.state.landspace ? '61' : '68') +
              'vh',
          }"
          class="q-mb-md"
          v-show="!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
                  v-if="false && clipboard.name == props.value"
                  :name="clipboard.type == 'COPY' ? 'file_copy' : 'content_cut'"
                  style="color: #ffbe4a; font-size: 2.5em"
                >
                </q-icon>
                <q-icon
                  :name="props.row.is_directory ? 'folder' : 'description'"
                  style="color: #ffbe4a; font-size: 2.5em"
                ></q-icon>
                {{
                  props.value.length > 60
                    ? props.value.substr(0, 60) + "..."
                    : 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="status != 'select'">
                  <div v-if="props.row.can_write">
                    <a
                      href="javascript:void(0)"
                      @click="(evt) => renameFile(props.row)"
                    >
                      {{ $t("rename") }}
                      <q-tooltip>
                        {{ $t("click") }}{{ $t("rename") }}
                      </q-tooltip>
                    </a>
                    &nbsp;&nbsp;&nbsp;&nbsp;
                    <a
                      href="javascript:void(0)"
                      @click="(evt) => copyFile(props.row)"
                    >
                      {{ $t("_copy2") }}
                      <q-tooltip>
                        {{ $t("click") }}{{ $t("_copy2") }}
                      </q-tooltip>
                    </a>
                    &nbsp;&nbsp;&nbsp;&nbsp;
                    <a
                      href="javascript:void(0)"
                      @click="(evt) => cutFile(props.row)"
                    >
                      {{ $t("_cut2") }}
                      <q-tooltip>
                        {{ $t("click") }}{{ $t("_cut2") }}
                      </q-tooltip>
                    </a>
                    &nbsp;&nbsp;&nbsp;&nbsp;
                    <a
                      href="javascript:void(0)"
                      @click="(evt) => deleteFile(props.row)"
                    >
                      {{ $t("delete") }}
                      <q-tooltip>
                        {{ $t("click") }}{{ $t("delete") }}
                      </q-tooltip>
                    </a>
                  </div>
                </div>
                <div v-else-if="!props.row.is_directory">
                  <a
                    href="javascript:void(0)"
                    @click="(evt) => selectFile(props.row)"
                  >
                    {{ $t("select file") }}
                    <q-tooltip>
                      {{ $t("click") }}{{ $t("select file") }}
                    </q-tooltip>
                  </a>
                </div>
              </div>
            </q-td>
          </template>
          <template v-slot:pagination="scope">
            <div class="col-2 text-h6">
              {{ $t("file count") }}: {{ file_count }}
            </div>
            <div class="col-2 text-h6 q-mx-md">&nbsp;&nbsp;&nbsp;&nbsp;</div>
            <div class="col-2 text-h6">
              {{ $t("directoriy count") }}: {{ directory_count }}
            </div>
            <div v-if="free_space" class="col-2 text-h6 q-mx-md">
              &nbsp;&nbsp;&nbsp;&nbsp;
            </div>

            <div class="col-2 text-h6" v-if="free_space">
              {{ $t("free space") }}:
              <span v-if="free_space / 1024 / 1024 / 1024 > 0">
                {{ (free_space / 1024 / 1024 / 1024).toFixed(1) }}GB
              </span>
              <span v-else>
                {{ (free_space / 1024 / 1024).toFixed(1) }}MB
              </span>
            </div>
          </template>
        </q-table>
        <div v-show="uploading" class="row q-ma-sm">
          <q-space />
          <q-uploader
            ref="uploader"
            style="height: 69vh; width: 70%"
            :disable="uploader_loading"
            :url="getUrl"
            method="post"
            :headers="generatorFileUploadHeaders"
            :label="$t('select file') + ':'"
            :accept="uploader_accept"
            @start="onStartUpload"
            @uploaded="onUploaded"
            @failed="onFailed"
            @added="/*onFileAdded*/ null"
          >
          </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
          v-if="false"
          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 name") }}</q-item-section>
        </q-item>
        <q-item
          clickable
          v-close-popup
          @click="(evt) => copyFile(current_file)"
        >
          <q-item-section avatar><q-icon name="file_copy" /></q-item-section>
          <q-item-section>{{ $t("_copy2") }}</q-item-section>
        </q-item>
        <q-item clickable v-close-popup @click="(evt) => cutFile(current_file)">
          <q-item-section avatar><q-icon name="content_cut" /></q-item-section>
          <q-item-section>{{ $t("_cut2") }}</q-item-section>
        </q-item>
        <q-item
          v-if="false"
          :disable="
            !(clipboard && clipboard.type && clipboard.type != 'NONE') ||
            path == clipboard.path
          "
          clickable
          v-close-popup
          @click="(evt) => pasteFile()"
        >
          <q-item-section avatar
            ><q-icon name="content_paste"
          /></q-item-section>
          <q-item-section>{{ $t("paste") }}</q-item-section>
        </q-item>
        <q-item
          clickable
          v-close-popup
          v-if="current_file && current_file.can_write && status != 'select'"
          @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 && status != 'select'"
          @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-item
          clickable
          v-close-popup
          v-if="status == 'select' && !current_file.is_directory"
          @click="(evt) => selectFile(current_file)"
        >
          <q-item-section avatar><q-icon name="attach_file" /></q-item-section>
          <q-item-section>{{ $t("select file") }}</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,
  Ref,
  reactive,
  watch,
  computed,
  nextTick,
} 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";
import NormalResult from "src/entities/NormalResult";
import { Protocol } from "src/entities/WSProtocol";
import FileSuffixHelper from "src/common/FileSuffixHelper";

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

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

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

class _ClipboardType {
  static kTypeNone = "NONE";
  static kTypeCopy = "COPY";
  static kTypeCut = "CUT";

  name: string = "";
  path: string = "";
  type: string = _ClipboardType.kTypeNone;
  is_directory = false;

  get full_path() {
    return this.path + "/" + this.name;
  }

  clear() {
    this.name = "";
    this.path = "";
    this.type = _ClipboardType.kTypeNone;
  }
}

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 uploader_loading = ref(false);
    let uploader_accept = ref("*");
    let uploading = ref(false);
    let files = ref(<FileEntity[]>[]);
    let show_context_menu = ref(false);
    let target_dom: any = ref(undefined);
    let current_file = ref(new FileEntity());
    let default_path_label = ref($t.t("local disk"));
    let default_path = ref("media");
    let path = ref(default_path.value);
    let prev_path = ref("");
    let paths = ref([new _BreadcrumbItem("root", "")]);
    let status = ref("normal");
    let upload_url = ref("");
    let uploader: any = ref(null);
    let resolve: any = null;
    let resolve_value: any = null;
    const filters: Ref<string[]> = ref([]);

    const free_space = ref(0);
    const file_count = ref(0);
    const directory_count = ref(0);

    const clipboard = reactive(new _ClipboardType()); // 剪切板全路径

    const disk_options = ref([
      {
        label: $t.t("local disk"),
        value: "media",
      },
    ]);

    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) {
          interface IRsponseData {
            files: FileEntity[];
            free: number;
          }
          let file_entitys: FileEntity[] = [];
          let free = 0;

          if (Array.isArray(response.data)) {
            file_entitys = response.data as FileEntity[];
          } else {
            const resposne_data = response.data as IRsponseData;
            file_entitys = resposne_data.files;
            free = resposne_data.free;
          }
          free_space.value = free;
          if (Array.isArray(file_entitys)) {
            directory_count.value = 0;
            file_count.value = 0;
            if (filters.value.length == 0) {
              files.value = file_entitys;
              for (const item of file_entitys) {
                if (item) {
                  if (item.is_directory) {
                    ++directory_count.value;
                  } else {
                    ++file_count.value;
                  }
                }
              }
            } else {
              files.value = [];
              for (const item of file_entitys) {
                if (item) {
                  if (item.is_directory) {
                    files.value.push(item);
                    ++directory_count.value;
                  } else {
                    for (const filter of filters.value) {
                      if (item.name.toLowerCase().endsWith(filter)) {
                        files.value.push(item);
                        ++file_count.value;
                        break;
                      }
                    }
                  }
                }
              }
            }
          } 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();
    };

    const parseFilter = (filter?: string) => {
      filters.value = [];
      console.log(filter);
      if (filter == null || typeof filter == "undefined") {
        return;
      }
      console.log(filter);

      if (filter) {
        for (const item of filter.split(";")) {
          if (item && item.length > 0) {
            filters.value.push(item);
          }
        }
      }
    };

    const selectFile = async (file: FileEntity) => {
      resolve_value = {
        file,
        path: path.value,
      };
      show_dialog.value = false;
    };

    watch(
      () => path.value,
      (newValue: string, oldValue: string) => {
        if (!newValue) {
          path.value = oldValue ?? default_path.value;
          return;
        }
        paths.value = [];
        let parent_item = null;
        const root_flag =
          path.value.startsWith("/") || path.value.startsWith("\\");
        for (let item of newValue.split("/")) {
          if (item.trim() == "") {
            parent_item = null;
            continue;
          }

          let temp: _BreadcrumbItem = new _BreadcrumbItem(
            item,
            (parent_item ? parent_item.path + "/" : "") + item
          );
          if (!parent_item && root_flag) {
            temp.path = "/" + temp.path;
          }

          paths.value.push(temp);
          parent_item = temp;
        }
        if (paths.value.length < 1) {
          paths.value.push(new _BreadcrumbItem("local disk", "media"));
        }
        refresh_file_list();
      }
    );

    watch(
      () => status.value,
      (newValue: string) => {
        switch (newValue) {
          case undefined:
          case null:
            status.value = "normal";
            break;
          case "normal":
          case "select":
            break;
          default:
            console.log("status error!", status.value);
            status.value = "normal";
        }
      }
    );

    watch(
      () => default_path.value,
      (newValue: string) => {
        let item = disk_options.value.find((item) => item.value == newValue);
        if (item && item.value && item.label) {
          default_path_label.value = item.label;
          path.value = default_path.value;
        }
      }
    );

    const refresh_usb_devices = async () => {
      try {
        const response = await GlobalData.getInstance()
          .getCurrentClient()
          ?.getUsbDevices();
        if (response) {
          disk_options.value = [
            {
              label: $t.t("local disk"),
              value: "media",
            },
          ];

          for (let item of response.usb_list) {
            disk_options.value.push({
              label: $t.t(item),
              value: "/" + item,
            });
          }
        }
      } catch (e) {
        console.log(e);
      }
    };

    // 后缀名限制
    // watch(
    //   () => filters.value,
    //   () => {
    //     if ($store.state.advanced_debug && filters.value.length != 0) {
    //       filters.value = [];
    //     }
    //   }
    // );

    return {
      show_dialog,
      loading,
      uploader_loading,
      uploader_accept,
      uploading,
      files,
      columns,
      show_context_menu,
      default_path,
      default_path_label,
      path,
      prev_path,
      paths,
      free_space,
      file_count,
      directory_count,
      target_dom,
      upload_url,
      uploader,
      disk_options,
      current_file,
      clipboard,
      refresh_file_list,
      refresh_file_list_async,
      status,
      filters,
      showDialogAsync(
        in_status: string,
        no_filter = true,
        video_filter = false,
        image_filter = false
      ) {
        return new Promise((_resolve, _reject) => {
          status.value = in_status;
          {
            let filter = "";
            if (!no_filter) {
              if (video_filter) {
                filter += FileSuffixHelper.videoSuffix;
              }
              if (image_filter) {
                filter += FileSuffixHelper.imageSuffix;
              }
            }
            parseFilter(filter);
            if (filter === "") {
              uploader_accept.value = "*";
            } else {
              uploader_accept.value = filter.replace(/;/g, ",");
            }
          }

          refresh_usb_devices();
          refresh_file_list();
          show_dialog.value = true;
          resolve = _resolve;
        });
      },
      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;
        uploading.value = false;
        files.value = [];
        path.value = default_path.value;
        status.value = "normal";
        upload_url.value = "";
        target_dom.value = undefined;
        clipboard.clear();
        if (resolve) {
          resolve(resolve_value);
        }
        resolve_value = null;
      },
      async onCreateNewFolder() {
        let url = GlobalData.getInstance().createCurrentRequestUrl();
        if (url) {
          $q.dialog({
            title: $t.t("create folder"),
            message: $t.t("input folder name") + ":",
            prompt: {
              model: "",
              isValid: (val: string) => !!val && val.trim().length > 0,
              type: "text",
            },
            cancel: true,
            persistent: true,
          }).onOk(async (data: string) => {
            if (url) {
              url.pathname = HttpProtocol.RequestPathCreateDirectory;
              let response = (
                await api.post(url.toString(), {
                  base_dir: path.value,
                  dir_name: data,
                })
              ).data as NormalResult;
              if (response && response.success) {
                refresh_file_list();
                $q.notify({
                  type: "positive",
                  message: $t.t("create folder") + $t.t("success") + "!",
                  position: "top",
                  timeout: 1500,
                });
              } else {
                $q.notify({
                  type: "warning",
                  message:
                    $t.t("create folder") +
                    $t.t("fail") +
                    "!" +
                    (response ? response.message : ""),
                  position: "top",
                  timeout: 1500,
                });
              }
            }
          });
        }
      },
      selectFile,
      async deleteFile(file: FileEntity) {
        let url = GlobalData.getInstance().createCurrentRequestUrl();
        if (url) {
          url.pathname = HttpProtocol.RequestPathDeleteFile;
          let response = null;
          try {
            response = (
              await api.delete(url.toString(), {
                data: {
                  base_dir: path.value,
                  file_name: file.name,
                },
              })
            ).data as NormalResult;
          } catch (e) {
            console.log(e);
          }
          if (response && response.success) {
            refresh_file_list();
            $q.notify({
              type: "positive",
              message: $t.t("delete file") + $t.t("success") + "!",
              position: "top",
              timeout: 1500,
            });
          } else {
            $q.notify({
              type: "warning",
              message:
                $t.t("delete file") +
                $t.t("fail") +
                "!" +
                (response ? response.message : ""),
              position: "top",
              timeout: 1500,
            });
          }
        }
      },
      renameFile(file: FileEntity) {
        let url = GlobalData.getInstance().createCurrentRequestUrl();
        if (url) {
          $q.dialog({
            title: $t.t("rename"),
            message: $t.t("input new file name") + ":",
            prompt: {
              model: file.name,
              isValid: (val: string) => !!val && val.trim().length > 0,
              type: "text",
            },
            cancel: true,
            persistent: true,
          }).onOk(async (data: string) => {
            if (data == file.name) {
              return;
            }
            if (url) {
              url.pathname = HttpProtocol.RequestPathRenameFile;
              url.searchParams.append(
                "type",
                HttpProtocol.RequestPathRenameFile
              );

              let response = (
                await api.put(url.toString(), {
                  base_dir: path.value,
                  file_name: file.name,
                  new_file_name: data,
                })
              ).data as NormalResult;
              if (response && response.success) {
                refresh_file_list();
                $q.notify({
                  type: "positive",
                  message: $t.t("file rename") + $t.t("success") + "!",
                  position: "top",
                  timeout: 1500,
                });
              } else {
                $q.notify({
                  type: "warning",
                  message:
                    $t.t("file rename") +
                    $t.t("fail") +
                    "!" +
                    (response ? response.message : ""),
                  position: "top",
                  timeout: 1500,
                });
              }
            }
          });
        }
      },
      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;
        } else if (status.value == "select" && !row.is_directory) {
          selectFile(row);
        }
      },
      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 url = GlobalData.getInstance().createCurrentRequestUrl();
        if (url) {
          url.pathname = HttpProtocol.RequestUploadFile;
          url.searchParams.append("type", HttpProtocol.HttpUploadTypeNormal);
          url.searchParams.append("base_dir", path.value);
          return url.toString();
        }
        return "#";
      },
      onStartUpload() {
        loading.value = true;
      },
      async onFileAdded(files: File[] | File) {
        setTimeout(async () => {
          const onError = async (file: File | null) => {
            await nextTick(() => {});
            uploader.value.reset();

            $q.notify({
              color: "negative",
              icon: "warning",
              message: $t.t("load file error") + "!",
              position: "top",
              timeout: 3000,
            });
          };

          let file: File | null = null;

          try {
            if (Array.isArray(files)) {
              if (files.length > 0) {
                file = files[0];
              }
            } else {
              file = files;
            }
            if (file) {
              const file_name = file.name;
              const blob = file.slice(0, 1024 * 1024 * 1); // 1 MB
              uploader_loading.value = true;

              try {
                let url = GlobalData.getInstance().createCurrentRequestUrl();
                if (url) {
                  url.pathname = HttpProtocol.RequestPathCheckFileSupport;

                  // if (FileSuffixHelper.isVideoPath(file_name)) {

                  // }
                  const data = new FormData();
                  data.append(
                    "file",
                    new File([blob], file_name, {
                      lastModified: file.lastModified,
                    })
                  );
                  const response = await api.post(url.toString(), data, {
                    headers: {
                      "Content-Type": "multipart/form-data",
                    },
                  });

                  if (response && response.data && response.data.is_support) {
                  } else {
                    onError(file);
                  }
                  console.log(response);
                } else {
                  throw "";
                }
              } catch (e) {
                console.error(e);
                onError(file);
              }
              uploader_loading.value = false;
              return;
            }
          } catch (e) {
            console.error(e);
            onError(file);
          }
        }, 1);
      },
      onUploaded() {
        uploading.value = false;
        uploader.value.reset();
        refresh_file_list();

        $q.notify({
          type: "positive",
          message: $t.t("file upload") + $t.t("success") + "!",
          position: "top",
          timeout: 1500,
        });
        loading.value = false;
      },
      onFailed(info: any) {
        console.log(info);
        $q.notify({
          type: "warning",
          message: $t.t("file upload") + $t.t("fail") + "!",
          position: "top",
          timeout: 1500,
        });
        loading.value = false;
        loading.value = false;
      },
      copyFile(file: FileEntity) {
        if (file) {
          clipboard.name = file.name;
          clipboard.path = path.value;
          clipboard.type = _ClipboardType.kTypeCopy;
          clipboard.is_directory = file.is_directory;
          $q.notify({
            color: "positive",
            icon: "done",
            html: true,
            message:
              $t.t("copy to colipboard success") +
              "!" +
              "<br />" +
              $t.t(
                "please use the paste command to paste to another directory"
              ) +
              "!",
            position: "top",
            timeout: 1500,
          });
        }
      },
      cutFile(file: FileEntity) {
        if (file) {
          clipboard.name = file.name;
          clipboard.path = path.value;
          clipboard.type = _ClipboardType.kTypeCut;
          clipboard.is_directory = file.is_directory;
          $q.notify({
            color: "positive",
            icon: "done",
            html: true,
            message:
              $t.t("cut to colipboard success") +
              "!" +
              "<br />" +
              $t.t(
                "please use the paste command to paste to another directory"
              ) +
              "!",
            position: "top",
            timeout: 1500,
          });
        }
      },
      pasteFile() {
        if (clipboard && clipboard.type) {
          let operator_type = "NONE";
          if (clipboard.type == _ClipboardType.kTypeCopy) {
            operator_type =
              Protocol.FileOperatorRequestEntity.kOperatorTypeCopy;
          } else if (clipboard.type == _ClipboardType.kTypeCut) {
            operator_type = Protocol.FileOperatorRequestEntity.kOperatorTypeCut;
          }
          $q.dialog({
            title: $t.t("Confirm"),
            html: true,
            message:
              (clipboard.type == _ClipboardType.kTypeCopy
                ? $t.t("_copy2")
                : $t.t("_cut2")) +
              (clipboard.is_directory ? $t.t("directory") : $t.t("file")) +
              $t.t("from") +
              ' "' +
              clipboard.full_path +
              '" ' +
              $t.t("to") +
              ' "' +
              (path.value + "/" + clipboard.name) +
              '"' +
              "<br/>" +
              "<span style='color:red;'>" +
              $t.t(
                "if the file size is too large, wait for the result patiently. don't refresh the page or perform other operations during the process. otherwise, unexpected consequences may occur"
              ) +
              "!" +
              "</span>",
            cancel: true,
            persistent: true,
          }).onOk(async () => {
            let success = false;
            loading.value = true;

            try {
              const reponse = await GlobalData.getInstance()
                .getCurrentClient()
                ?.fileOperator(
                  clipboard.full_path,
                  path.value + "/" + clipboard.name,
                  operator_type
                );
              success = reponse?.success ?? false;
            } catch {}
            loading.value = false;
            if (success) {
              refresh_file_list_async();
            }
            $q.notify({
              color: success ? "positive" : "negative",
              icon: success ? "done" : "warning",
              message:
                (clipboard.type == _ClipboardType.kTypeCopy
                  ? $t.t("_copy2")
                  : $t.t("_cut2")) +
                (clipboard.is_directory ? $t.t("directory") : $t.t("file")) +
                (success ? $t.t("success") : $t.t("fail")) +
                "!",
              position: "top",
              timeout: 1500,
            });
          });
        }
      },
    };
  },
});
</script>
