<template>
  <div>
    <q-scroll-area
      :style="{ height: content_height + 'px' }"
      style="width: 20vw"
    >
      <q-tree ref="tree" :nodes="tree_nodes" node-key="uuid" labelKey="name">
        <template v-slot:default-header="prop">
          <q-item
            class="full-width"
            clickable
            :disable="!$store.state.power_state"
            :draggable="prop.node.uuid != '' && $store.state.power_state"
            @dragstart="(evt) => onDragStart(evt, prop.node)"
            @dragover="(evt) => onDragOver(evt, prop.node)"
            @drop="(evt) => onDrop(evt, prop.node)"
            @dblclick="
              (evt) => {
                if (!$store.state.power_state) {
                  return;
                }
                if (prop.node.is_group) {
                  return;
                }
                if (
                  $store.state.current_running_plan.trim() == '' &&
                  !prop.node.is_group
                ) {
                  callMode(prop.node.item_data);
                } else {
                  $q.notify({
                    type: 'warning',
                    message: $t('plan running! can\'t call mode!'),
                    position: 'top',
                    timeout: 1500,
                  });
                }
              }
            "
          >
            <q-item-section avatar>
              <q-icon
                style="pointer-events: none"
                :name="
                  prop.node.is_group
                    ? 'img:source_icon/group.png'
                    : 'img:new_icon/mode_icon.png'
                "
                color="orange"
                size="28px"
                class="q-mr-sm"
              />
            </q-item-section>
            <q-item-section>
              <div class="text-weight-bold text-primary">
                <span v-if="prop.node.item_data && !prop.node.is_group"
                  >({{ prop.node.item_data?.number }})
                </span>
                &nbsp;&nbsp;{{ prop.node.name }}
              </div>
            </q-item-section>
            <q-popup-proxy :context-menu="$store.state.power_state">
              <q-list>
                <q-item
                  v-if="
                    prop.node.name == $t('mode') ||
                    (prop.node.is_group && prop.node.item_data)
                  "
                  clickable
                  v-close-popup
                  v-ripple
                  @click="
                    $refs.mode_dialog.showDialog({
                      type: 1,
                      data: { uuid: prop.node.uuid },
                    })
                  "
                >
                  <q-item-section avatar><q-icon name="add" /></q-item-section>
                  <q-item-section>{{ $t("add mode item") }}</q-item-section>
                </q-item>
                <q-item
                  clickable
                  v-close-popup
                  v-if="
                    prop.node.name == $t('mode') ||
                    (prop.node.is_group && prop.node.item_data)
                  "
                  v-ripple
                  @click="
                    () =>
                      $refs.group_dialog.showDialog({
                        type: 1,
                        data: prop.node,
                      })
                  "
                >
                  <q-item-section avatar
                    ><q-icon name="create_new_folder"
                  /></q-item-section>
                  <q-item-section>{{ $t("add group") }}</q-item-section>
                </q-item>

                <q-item
                  clickable
                  v-ripple
                  v-close-popup
                  v-if="prop.node.item_data && !prop.node.is_group"
                  @click="updateToCurrentWindowList($event, prop.node)"
                >
                  <q-item-section avatar
                    ><q-icon name="refresh"
                  /></q-item-section>
                  <q-item-section>{{
                    $t("update to current window list")
                  }}</q-item-section>
                </q-item>

                <q-item
                  clickable
                  v-ripple
                  v-close-popup
                  v-if="prop.node.item_data && prop.node.item_data.uuid"
                  @click="
                    () =>
                      (prop.node.is_group
                        ? $refs.group_dialog
                        : $refs.mode_dialog
                      ).showDialog({
                        type: 2,
                        data: prop.node,
                      })
                  "
                >
                  <q-item-section avatar><q-icon name="edit" /></q-item-section>
                  <q-item-section>{{ $t("edit") }}</q-item-section>
                </q-item>

                <q-item
                  clickable
                  v-ripple
                  v-close-popup
                  v-if="prop.node.item_data && prop.node.item_data.uuid"
                  @click="
                    (evt) => deleteItem(evt, prop.node.is_group, prop.node.uuid)
                  "
                >
                  <q-item-section avatar
                    ><q-icon color="red" name="delete"
                  /></q-item-section>
                  <q-item-section>{{ $t("delete") }} &nbsp;</q-item-section>
                </q-item>
              </q-list>
            </q-popup-proxy>
          </q-item>
        </template>
      </q-tree>
    </q-scroll-area>
  </div>
  <mode-group-dialog ref="group_dialog" />
  <mode-dialog ref="mode_dialog" />
</template>

<script lang="ts">
import { defineComponent, computed, onMounted, ref, nextTick } from "vue";
import { useStore } from "src/store";
import ModeGroupDialog from "src/components/ModeGroupDialog.vue";
import ModeDialog from "src/components/ModeDialog.vue";
import { Common } from "src/common/Common";
import GlobalData from "src/common/GlobalData";
import { useQuasar, extend } from "quasar";
import { useI18n } from "vue-i18n";
import { ModeEntity, ModeTreeItemEntity } from "src/entities/ModeEntity";
import EventBus, { EventNamesDefine } from "src/common/EventBus";
import { NotifyMessage } from "src/common/ClientConnection";
import { Protocol } from "src/entities/WSProtocol";

export default defineComponent({
  name: "ComponentModeTree",

  components: { ModeGroupDialog, ModeDialog },

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

    const tree_nodes = computed({
      get: () => $store.state.mode_tree,
      set: (val) => {},
    });

    const content_height = ref(0);

    const refresh_content_height = () => {
      content_height.value = window.innerHeight - 135;
    };
    refresh_content_height();

    EventBus.getInstance().on(EventNamesDefine.WindowResize, () => {
      refresh_content_height();
    });

    const tree: any | null = ref(null);

    onMounted(async () => {
      while (!tree.value?.nodes?.length) {
        await Common.waitFor(100);
      }
      tree.value?.setExpanded("", true);
    });

    return {
      tree,
      tree_nodes,
      content_height,
      loga(a: any) {
        console.log(a);
      },
      deleteItem(evt: PointerEvent | null, is_group: boolean, uuid: string) {
        const show_tooltip = (success: boolean) => {
          $q.notify({
            color: success ? "positive" : "negative",
            icon: success ? "done" : "warning",
            message:
              $t.t("delete") + (success ? $t.t("success") : $t.t("fail")) + "!",
            position: "top",
            timeout: 1500,
          });
        };
        let success = false;
        if (is_group) {
          $q.dialog({
            title: $t.t("Confirm"),
            message: $t.t(
              "delete group should be delete all child! do you want to delete this group?"
            ),
            ok: {
              label: $t.t("ok"),
              noCaps: true,
              flat: true,
            },
            cancel: {
              label: $t.t("cancel"),
              noCaps: true,
              flat: true,
            },
            persistent: true,
          }).onOk(async () => {
            let response = await GlobalData.getInstance()
              .getCurrentClient()
              ?.deleteModeGroup(uuid);
            if (response) {
              success = response.success;
            }
            show_tooltip(success);
          });
        } else {
          $q.dialog({
            title: $t.t("Confirm"),
            message: $t.t("do you want to delete the item") + "?",
            ok: {
              label: $t.t("ok"),
              noCaps: true,
              flat: true,
            },
            cancel: {
              label: $t.t("cancel"),
              noCaps: true,
              flat: true,
            },
            persistent: true,
          }).onOk(async () => {
            let response = await GlobalData.getInstance()
              .getCurrentClient()
              ?.deleteMode(uuid);
            if (response) {
              success = response.success;
            }
            show_tooltip(success);
          });
        }
      },
      callMode(item: ModeEntity) {
        GlobalData.getInstance().getCurrentClient()?.callMode(item.uuid);
        $q.notify({
          color: "positive",
          icon: "done",
          message: $t.t("call mode directives send") + $t.t("success") + "!",
          position: "top",
          timeout: 1500,
        });
      },
      updateToCurrentWindowList(evt: MouseEvent, data: ModeTreeItemEntity) {
        if (
          data &&
          data.item_data &&
          data.item_data.uuid &&
          data.item_data.uuid.trim() != ""
        ) {
          const uuid = data.item_data.uuid;
          $q.dialog({
            title: $t.t("update to current window list"),
            message:
              $t.t(
                "the list of previously saved window list is about to be overwritten"
              ) +
              "," +
              $t.t("are you sure about the update") +
              "?",
            ok: {
              label: $t.t("ok"),
              noCaps: true,
              flat: true,
            },
            cancel: {
              label: $t.t("cancel"),
              noCaps: true,
              flat: true,
            },
            persistent: true,
          }).onOk(async () => {
            try {
              const response = (await GlobalData.getInstance()
                .getCurrentClient()
                ?.updateModeWindowList(
                  uuid
                )) as Protocol.UpdateModeWindowListResponseEntity;

              $q.notify({
                color: response && response.success ? "positive" : "negative",
                icon: response && response.success ? "done" : "warning",
                message:
                  $t.t("update to current window list") +
                  (response && response.success
                    ? $t.t("success")
                    : $t.t("fail")) +
                  "!",
                position: "top",
                timeout: 1500,
              });
            } catch (e) {
              console.log(e);
            }
          });
        }
      },
      onDragStart(e: DragEvent, node: ModeTreeItemEntity) {
        e.dataTransfer?.setData("uuid", node.uuid);
        e.dataTransfer?.setData("type", "mode");
        e.dataTransfer?.setData("group", node.is_group ? "true" : "false");
        e.dataTransfer?.setData("node_object", JSON.stringify(node));
        if (e.dataTransfer) {
          e.dataTransfer.dropEffect = "move";
        }
      },
      onDragOver(e: DragEvent, node: ModeTreeItemEntity) {
        if (node && node.is_group) {
          e.preventDefault();
        }
      },
      onDrop(e: DragEvent, node: ModeTreeItemEntity) {
        if (node && node.is_group && node.item_data) {
          if (e.dataTransfer) {
            const type = e.dataTransfer.getData("type");
            if (type == "mode") {
              const uuid = e.dataTransfer.getData("uuid");
              const group = e.dataTransfer.getData("group");
              if (
                typeof uuid == "string" &&
                type &&
                type.length > 0 &&
                group &&
                group.length > 0
              ) {
                if (group == "true") {
                  const mode_group = GlobalData.getInstance().mode_groups.find(
                    (item) => item && (item as any).uuid == uuid
                  );
                  if (mode_group) {
                    if (mode_group.parent_uuid == node.item_data.uuid) {
                      return;
                    }

                    GlobalData.getInstance()
                      .getCurrentClient()
                      ?.editModeGroup(
                        mode_group.uuid,
                        mode_group.name,
                        node.item_data.uuid
                      );
                  } else {
                    console.log("can't find mode group, uuid:" + uuid);
                  }
                } else if (group == "false") {
                  const mode = GlobalData.getInstance().modes.find(
                    (item) => item && (item as any).uuid == uuid
                  );
                  if (mode) {
                    if (mode.group_uuid == node.item_data.uuid) {
                      return;
                    }
                    GlobalData.getInstance()
                      .getCurrentClient()
                      ?.editMode(
                        mode.uuid,
                        mode.name,
                        mode.number,
                        node.item_data.uuid
                      );
                  } else {
                    console.log("can't find mode, uuid:" + uuid);
                  }
                }
              }
            } else {
              console.log("type error");
            }
          }
        }
      },
    };
  },
});
</script>