<template>
  <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 &&
            (!prop.node.item_data.system_default || !prop.node.is_group)
          "
          @dragstart="(evt) => onDragStart(evt, prop.node)"
          @dragover="(evt) => onDragOver(evt, prop.node)"
          @drop="(evt) => onDrop(evt, prop.node)"
          @click="
            $store.commit(
              'setSelectedSignalSource',
              prop.node.is_group
                ? $store.state.selected_signal_source
                : prop.node.uuid
            )
          "
          :style="{
            border:
              $store.state.selected_signal_source == prop.node.uuid
                ? '1px solid #aacceec2'
                : 'none',
          }"
        >
          <!-- {{ prop.node }} -->
          <q-item-section avatar>
            <q-icon
              style="pointer-events: none"
              :name="
                prop.node.is_group
                  ? 'img:source_icon/group.png'
                  : getItemIcon(prop.node.item_data?.window_type)
              "
              color="orange"
              size="28px"
              class="q-mr-sm"
            />
          </q-item-section>
          <q-item-section>
            <div class="text-weight-bold text-primary">
              {{ prop.node.name }}
            </div>
          </q-item-section>
          <q-popup-proxy
            :context-menu="$store.state.power_state"
            @before-show="updateContextMenu"
          >
            <q-list>
              <q-item
                clickable
                v-ripple
                v-close-popup
                v-if="prop.node.item_data?.window_type == 'EwindowType::HdmiIn'"
                @click="setHdmiInDecodeType(1, 'NV12')"
              >
                <q-item-section>
                  {{ $t("lossy ") + $t("picture quality") }}
                </q-item-section>
                <q-item-section side v-if="lossy_pic">
                  <q-icon name="done" />
                </q-item-section>
              </q-item>
              <q-item
                clickable
                v-ripple
                v-close-popup
                v-if="prop.node.item_data?.window_type == 'EwindowType::HdmiIn'"
                @click="setHdmiInDecodeType(1, 'NV16')"
              >
                <q-item-section>
                  {{ $t("lossless ") + $t("picture quality") }}
                </q-item-section>
                <q-item-section side v-if="!lossy_pic">
                  <q-icon name="done" />
                </q-item-section>
              </q-item>
              <q-item
                clickable
                v-ripple
                v-if="
                  $store.state.isSpecialVideo() &&
                  prop.node.item_data?.window_type == 'EwindowType::HdmiIn'
                "
              >
                <q-item-section>
                  {{ $t("rotation") }}
                </q-item-section>
                <q-item-section side>
                  <q-icon name="keyboard_arrow_right" />
                </q-item-section>
                <q-menu
                  @before-show="updateCurrentHdmiRotation"
                  anchor="top end"
                  self="top start"
                >
                  <q-list>
                    <q-item
                      v-close-popup
                      v-for="n in [0, 90, 180, 270]"
                      :key="n"
                      clickable
                      @click="setHDMIRotation(n)"
                    >
                      <q-item-section>{{ n }}°</q-item-section>
                      <q-item-section side>
                        <q-icon v-if="n == current_hdmi_rotation" name="done" />
                      </q-item-section>
                    </q-item>
                  </q-list>
                </q-menu>
              </q-item>
              <q-item
                clickable
                v-ripple
                v-if="
                  hw_version == 2 &&
                  prop.node.item_data?.window_type == 'EwindowType::HdmiIn'
                "
              >
                <q-item-section>
                  {{ $t("hdmi audio frequency acquisition device") }}
                </q-item-section>
                <q-item-section side>
                  <q-icon name="keyboard_arrow_right" />
                </q-item-section>
                <q-menu
                  @before-show="updateCurrentHdmiAudioDevice"
                  anchor="top end"
                  self="top start"
                >
                  <q-list>
                    <q-item
                      v-close-popup
                      v-for="item in [
                        {
                          label: 'hdmi internal',
                          value: '',
                        },
                        {
                          label: '3.5mm',
                          value: '3.5mm',
                        },
                      ]"
                      :key="item.value"
                      clickable
                      @click="setHdmiInAudioDevice(1, item.value)"
                    >
                      <q-item-section>{{ $t(item.label) }}</q-item-section>
                      <q-item-section side>
                        <q-icon
                          v-if="item.value == current_hdmi_audio_device"
                          name="done"
                        />
                      </q-item-section>
                    </q-item>
                  </q-list>
                </q-menu>
              </q-item>

              <q-item
                v-if="
                  prop.node.name == $t('signal source') ||
                  (prop.node.is_group &&
                    prop.node.item_data &&
                    !prop.node.item_data.system_default)
                "
                clickable
                v-close-popup
                v-ripple
                @click="
                  $refs.signal_source_dialog.showDialog({
                    type: 1,
                    parent_node: prop.node.uuid,
                  })
                "
              >
                <q-item-section avatar><q-icon name="add" /></q-item-section>
                <q-item-section>{{
                  $t("add signal source item")
                }}</q-item-section>
              </q-item>
              <q-item
                clickable
                v-close-popup
                v-if="
                  prop.node.name == $t('signal source') ||
                  (prop.node.is_group &&
                    prop.node.item_data &&
                    !prop.node.item_data.system_default)
                "
                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.item_data.uuid &&
                  !prop.node.item_data.system_default
                "
                @click="
                  () =>
                    (prop.node.is_group
                      ? $refs.group_dialog
                      : $refs.signal_source_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 &&
                  !prop.node.item_data.system_default
                "
                @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>
  <signal-source-group-dialog ref="group_dialog" />
  <signal-source-dialog ref="signal_source_dialog" />
</template>

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

export default defineComponent({
  name: "ComponentSignalSourceTree",

  components: { SignalSourceGroupDialog, SignalSourceDialog },

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

    const lossy_pic = ref(false);
    const hw_version = ref(1);

    const content_height = ref(0);

    const current_hdmi_rotation = ref(0);
    const current_hdmi_audio_device = ref("");

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

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

    const tree_nodes = computed({
      get: () => $store.state.signal_source_tree,
      set: (val) => $store.commit("setSignalSourceTree", val),
    });

    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,
      lossy_pic,
      current_hdmi_rotation,
      hw_version,
      current_hdmi_audio_device,

      loga(a: any) {
        console.log(a);
      },
      onDragStart(e: DragEvent, node: SignalSourceTreeItemEntity) {
        e.dataTransfer?.setData("uuid", node.uuid);
        e.dataTransfer?.setData("type", "signal_source");
        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: SignalSourceTreeItemEntity) {
        if (node && node.is_group && !node.item_data?.system_default) {
          e.preventDefault();
        }
      },
      onDrop(e: DragEvent, node: SignalSourceTreeItemEntity) {
        if (
          node &&
          node.is_group &&
          node.item_data &&
          !node.item_data.system_default
        ) {
          if (e.dataTransfer) {
            const type = e.dataTransfer.getData("type");
            if (type == "signal_source") {
              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 signal_source_group =
                    GlobalData.getInstance().signal_source_groups.find(
                      (item) => item && (item as any).uuid == uuid
                    );
                  if (signal_source_group) {
                    if (signal_source_group.system_default) {
                      return;
                    }
                    if (
                      signal_source_group.parent_uuid == node.item_data.uuid
                    ) {
                      return;
                    }
                    GlobalData.getInstance()
                      .getCurrentClient()
                      ?.editSignalSourceGroup(
                        signal_source_group.uuid,
                        signal_source_group.name,
                        node.item_data.uuid
                      );
                  } else {
                    console.log("can't find signal source group, uuid:" + uuid);
                  }
                } else if (group == "false") {
                  const signal_source =
                    GlobalData.getInstance().signal_source.find(
                      (item) => item && (item as any).uuid == uuid
                    );
                  if (signal_source) {
                    if (signal_source.system_default) {
                      return;
                    }

                    if (signal_source.group_uuid == node.item_data.uuid) {
                      return;
                    }
                    const entity = extend(
                      false,
                      signal_source
                    ) as SignalSourceEntity;
                    entity.group_uuid = node.item_data.uuid;
                    GlobalData.getInstance()
                      .getCurrentClient()
                      ?.editSignalSource(entity);
                  } else {
                    console.log("can't find signal source, uuid:" + uuid);
                  }
                }
              }
            } else {
              console.log("type error");
            }
          }
        }
      },
      getItemIcon(item_type: string) {
        return Common.getSignalSourceIcon(item_type);
      },
      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,
          });
        };
        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 success = false;

            let response = await GlobalData.getInstance()
              .getCurrentClient()
              ?.deleteSignalSourceGroup(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 success = false;

            let response = await GlobalData.getInstance()
              .getCurrentClient()
              ?.deleteSignalSource(uuid);
            if (response) {
              success = response.success;
            }
            show_tooltip(success);
          });
        }
      },
      updateContextMenu() {
        lossy_pic.value =
          GlobalData.getInstance().applicationConfig?.hdmi_in_decode_type_1 ==
          "NV12";

        const num = parseInt(
          GlobalData.getInstance().applicationConfig?.hw_version ?? "1"
        );
        if (isNaN(num)) {
          hw_version.value = 1;
        } else {
          hw_version.value = num;
        }
      },
      async setHdmiInDecodeType(index: number, type: string) {
        let success = false;

        const response = await GlobalData.getInstance()
          .getCurrentClient()
          ?.setHdmiInDecodeType(index, type);

        if (response) {
          success = response.success;
        }

        $q.notify({
          color: success ? "positive" : "negative",
          icon: success ? "done" : "warning",
          message:
            $t.t("set") + (success ? $t.t("success") : $t.t("fail")) + "!",
          position: "top",
          timeout: 1500,
        });
      },
      updateCurrentHdmiRotation() {
        current_hdmi_rotation.value =
          GlobalData.getInstance().applicationConfig?.device_hdmi_rotation ?? 0;
      },
      updateCurrentHdmiAudioDevice() {
        current_hdmi_audio_device.value =
          GlobalData.getInstance().applicationConfig?.hdmi_in_audio_device_1 ??
          "";
        switch (current_hdmi_audio_device.value) {
          case "":
          case "3.5mm":
            break;
          default:
            current_hdmi_audio_device.value = "";
            break;
        }
      },
      async setHdmiInAudioDevice(index: number, device: string) {
        let success = false;

        const response = await GlobalData.getInstance()
          .getCurrentClient()
          ?.setHdmiInAudioDevice(index, device);

        if (response) {
          success = response.success;
        }

        $q.notify({
          color: success ? "positive" : "negative",
          icon: success ? "done" : "warning",
          message:
            $t.t("set") + (success ? $t.t("success") : $t.t("fail")) + "!",
          position: "top",
          timeout: 1500,
        });
      },
      setHDMIRotation(rotation: number) {
        let success = true;
        try {
          GlobalData.getInstance()
            .getCurrentClient()
            ?.setHdmiRotation(rotation);
        } catch {
          success = false;
        }
        $q.notify({
          color: success ? "positive" : "negative",
          icon: success ? "done" : "warning",
          message:
            $t.t("set") + (success ? $t.t("success") : $t.t("fail")) + "!",
          position: "top",
          timeout: 1500,
        });
      },
    };
  },
});
</script>
