<template>
  <q-dialog
    persistent
    v-model="show_dialog"
    @before-hide="resetData"
    @keydown="
      (evt) => {
        if (!loading && evt.keyCode == 27) {
          show_dialog = false;
        }
      }
    "
  >
    <q-popup-proxy context-menu></q-popup-proxy>
    <q-card class="overflow-hidden" style="overflow-y: scroll; max-width: 60vw">
      <q-form @submit="onSubmit">
        <q-card-section class="q-ma-none q-pa-sm">
          <div class="row">
            <div class="col-auto text-h6">
              {{ $t("video wall") }}
            </div>
            <q-space />
            <div>
              <q-btn
                :loading="loading"
                flat
                round
                icon="close"
                :disable="loading"
                color="red"
                v-close-popup
              >
                <q-tooltip>
                  {{ $t("close") }}
                </q-tooltip>
              </q-btn>
            </div>
          </div>
        </q-card-section>

        <q-separator />

        <q-card-section style="max-height: 68vh; width: 55vw" class="scroll">
          <q-list>
            <q-item>
              <q-item-section avatar class="head_1">
                {{ $t("screen mode") }}
              </q-item-section>
              <q-item-section>
                <q-select
                  v-model="screen_mode"
                  :options="[
                    {
                      label: $t('landspace mode'),
                      value: 0,
                    },
                    {
                      label: $t('portrait mode'),
                      value: 1,
                    },
                  ]"
                  emit-value
                  map-options
                  :loading="loading"
                  :disable="loading"
                >
                </q-select>
              </q-item-section>
            </q-item>

            <q-item>
              <q-item-section avatar class="head_1">
                {{ $t("splice mode") }}
              </q-item-section>
              <q-item-section>
                <q-select
                  v-model="splice_mode"
                  :options="screen_mode == 0 ? landspace_modes : portrait_modes"
                  emit-value
                  map-options
                  :rules="[
                    (val) =>
                      val != 'Other' ||
                      $t('splice mode') +
                        $t(' ') +
                        $t('can\'t be') +
                        $t(' ') +
                        'Other',
                  ]"
                  :loading="loading"
                  :disable="loading"
                >
                </q-select>
              </q-item-section>
            </q-item>
          </q-list>
        </q-card-section>

        <q-separator />

        <q-card-section style="width: 60vw">
          <div style="max-height: 50vh">
            <div
              ref="preview_grid"
              style="height: 100%; width: 98%"
              class="preview_grid1 items-center justify-center"
            >
              <div
                v-for="row in preview_rows"
                :key="'row' + (row - 1)"
                class="row items-center justify-center"
              >
                <div
                  v-for="col in preview_cols"
                  :style="{
                    height: previce_grid_height + 'px',
                    width: previce_grid_width + 'px',
                  }"
                  class="preview_grid_item row items-center justify-center"
                  :key="(row - 1) * preview_cols + col"
                >
                  <div class="fit row items-center justify-center">
                    <div class="preview_wall_item" style="font-size: 0.8rem">
                      <span>
                        &nbsp;&nbsp;HDMI Port:
                        {{ (row - 1) * preview_cols + col }}
                      </span>
                      <br />
                      <span
                        v-if="
                          outputs.length > (row - 1) * preview_cols + col - 1
                        "
                      >
                        &nbsp;&nbsp;Splice Index:
                        {{
                          (outputs[(row - 1) * preview_cols + col - 1]
                            .output_index ?? (row - 1) * preview_cols + col) + 1
                        }}</span
                      >
                      <br />
                      <span
                        v-if="
                          (preview_rotation == 1 || preview_rotation == 180) &&
                          row == 1
                        "
                      >
                        (180°)
                      </span>
                    </div>
                    <q-popup-proxy context-menu>
                      <q-item
                        clickable
                        v-close-popup
                        @click="
                          setSpliceIndex(
                            (row - 1) * preview_cols + col - 1,
                            outputs[(row - 1) * preview_cols + col - 1]
                              .output_index ?? (row - 1) * preview_cols + col
                          )
                        "
                      >
                        <q-item-section>{{
                          $t("set splice index")
                        }}</q-item-section>
                      </q-item>
                    </q-popup-proxy>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </q-card-section>

        <q-separator />

        <q-card-actions>
          <q-space />
          <q-btn
            :loading="loading"
            flat
            no-caps
            :label="$t('close')"
            color="primary"
            v-close-popup
            :disable="loading"
          />
          <q-btn
            ref="accept"
            flat
            no-caps
            :label="$t('accept')"
            :loading="loading"
            type="submit"
            color="primary"
          />
        </q-card-actions>
      </q-form>
    </q-card>
  </q-dialog>
</template>

<style scoped>
.head_1 {
  width: 25%;
}

.head_2 {
  width: 12%;
}

.preview_grid {
  border: 1px solid gray;
}

.preview_grid_item {
  border: 1px solid gray;
}
</style>

<script lang="ts">
import {
  defineComponent,
  ref,
  Ref,
  watch,
  computed,
  onMounted,
  nextTick,
} from "vue";
import { useStore } from "src/store";
import { useQuasar, date as DateHelper } from "quasar";
import { useI18n } from "vue-i18n";
import GlobalData from "src/common/GlobalData";
import OutputBoardItemConfigEntity from "src/entities/OutputBoardItemConfigEntity";
import EventBus, { EventNamesDefine } from "src/common/EventBus";
const elementResizeDetectorMaker = require("element-resize-detector");

export default defineComponent({
  name: "ComponentCustomISVVideoWallDialog",
  components: {},

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

    let show_dialog = ref(false);
    let loading = ref(false);

    const landspace_modes = [
      "2x2",
      "2x2 (180°)",
      "1x2",
      "1x3",
      "1x4",
      "2x1",
      "2x1 (180°)",
      "3x1",
      "4x1",
      "Other",
    ];
    const portrait_modes = [
      "2x2",
      "1x2",
      "1x3",
      "1x4",
      "2x1",
      "3x1",
      "4x1",
      "Other",
    ];

    const screen_mode = ref(0);
    const splice_mode = ref("");

    const preview_grid: Ref<HTMLElement | null> = ref(null);
    const preview_rows = ref(3);
    const preview_cols = ref(3);
    const preview_rotation = ref(0);
    const previce_grid_height = ref(100);
    const previce_grid_width = ref(80);
    const outputs: Ref<OutputBoardItemConfigEntity[]> = ref(
      <OutputBoardItemConfigEntity[]>[]
    );

    class parseSpliceModeResult {
      rotation = 0;
      rows = 2;
      cols = 2;
    }
    const parseSpliceMode = (splice_mode: string) => {
      splice_mode = splice_mode.toLowerCase();
      const result = new parseSpliceModeResult();
      const space_index = splice_mode.indexOf(" ");
      if (space_index != -1) {
        const rotation = splice_mode
          .substring(space_index + 1)
          .replace(/\(|\)|°/g, "")
          .trim();
        const temp = parseInt(rotation);
        if (!isNaN(temp)) {
          result.rotation = temp;
        }
        splice_mode = splice_mode.substring(0, space_index).trim();
      }

      const x_index = splice_mode.indexOf("x");
      if (x_index != -1) {
        const rows = splice_mode.substring(0, x_index).trim();
        const cols = splice_mode.substring(x_index + 1).trim();
        let temp = parseInt(rows);
        if (!isNaN(temp)) {
          result.rows = temp;
        }
        temp = parseInt(cols);
        if (!isNaN(temp)) {
          result.cols = temp;
        }
      }
      return result;
    };

    const refreshPreviewGridWH = () => {
      if (preview_grid.value) {
        let max_height = window.innerHeight * 0.49; // items-center justify-center
        let max_width = preview_grid.value.clientWidth * 0.95;
        max_width = (max_width - preview_cols.value) & ~preview_cols.value;
        max_height = (max_height - preview_rows.value) & ~preview_rows.value;

        let cell_width = 0;
        let cell_height = 0;
        if (screen_mode.value == 0) {
          cell_width = max_width / preview_cols.value;
          cell_height = (cell_width * 9) / 16;
          if (cell_height * preview_rows.value > max_height) {
            cell_height = max_height / preview_rows.value;
            cell_width = (cell_height * 16) / 9;
          }
        } else {
          cell_height = max_height / preview_rows.value;
          if (preview_cols.value == 1 && preview_rows.value == 4) {
            cell_width = (cell_height * 16) / 16;
          } else {
            cell_width = (cell_height * 12) / 16;
          }
          if (cell_width * preview_cols.value > max_width) {
            cell_width = max_width / preview_cols.value;
            if (preview_cols.value == 1 && preview_rows.value == 4) {
              cell_height = (cell_width * 16) / 16;
            } else {
              cell_height = (cell_width * 16) / 12;
            }
          }
        }

        previce_grid_width.value = cell_width;
        previce_grid_height.value = cell_height;
      }
    };

    watch(
      () => splice_mode.value,
      (newV: string) => {
        const result = parseSpliceMode(newV);
        preview_cols.value = result.cols;
        preview_rows.value = result.rows;
        preview_rotation.value = result.rotation;

        refreshPreviewGridWH();
      }
    );

    watch(
      () => screen_mode.value,
      (newV, oldV) => {
        if (oldV == 0 && newV == 1) {
          const result = parseSpliceMode(splice_mode.value);
          splice_mode.value = result.rows + "x" + result.cols;
        }
        refreshPreviewGridWH();
      }
    );

    EventBus.getInstance().on(
      EventNamesDefine.WindowResize,
      refreshPreviewGridWH
    );

    return {
      show_dialog,
      loading,
      screen_mode,
      splice_mode,
      landspace_modes,
      portrait_modes,
      preview_grid,
      preview_rows,
      preview_cols,
      preview_rotation,
      previce_grid_height,
      outputs,
      previce_grid_width,

      async showDialog() {
        {
          const temp = parseInt(
            (
              GlobalData.getInstance().applicationConfig?.device_rotate ?? 0
            ).toString()
          );
          if (isNaN(temp)) {
            screen_mode.value = 0;
          } else {
            screen_mode.value = temp == 90 || temp == 1 ? 1 : 0;
          }
        }

        {
          const video_wall_config = await GlobalData.getInstance()
            .getCurrentClient()
            ?.customConnection.getVideoWallConfig();
          outputs.value = video_wall_config?.outputs ?? [];
          if (video_wall_config) {
            if (screen_mode.value == 0) {
              splice_mode.value =
                video_wall_config.wall_rows.toString() +
                "x" +
                video_wall_config.wall_cols.toString();
            } else {
              splice_mode.value =
                video_wall_config.wall_cols.toString() +
                "x" +
                video_wall_config.wall_rows.toString();
            }

            if (
              Array.isArray(video_wall_config.outputs) &&
              video_wall_config?.outputs.length > 0
            ) {
              let index = video_wall_config.outputs[0].index;
              let pos = 0;
              for (let i = 0; i < video_wall_config.outputs.length; ++i) {
                if (video_wall_config.outputs[i].index < index) {
                  index = video_wall_config.outputs[i].index;
                  pos = i;
                }
              }

              if (
                (screen_mode.value == 0 &&
                  video_wall_config.outputs[pos].rotation == 1) ||
                video_wall_config.outputs[pos].rotation == 180
              ) {
                splice_mode.value += " (180°)";
              }
              // preview_rotation.value = video_wall_config.outputs[pos].rotation;
            }
          }

          const temp_array =
            screen_mode.value == 0 ? landspace_modes : portrait_modes;
          const temp = temp_array.find((e) => e && e == splice_mode.value);
          if (!temp) {
            splice_mode.value = "Other";
          }
        }

        nextTick(() => {
          refreshPreviewGridWH();
        });
        show_dialog.value = true;
      },
      resetData() {
        loading.value = false;
      },
      async onSubmit() {
        loading.value = true;
        let success = false;
        try {
          const result = parseSpliceMode(splice_mode.value);

          const rotation_180_outputs = <number[]>[];
          if (result.rotation == 180) {
            for (let i = 0; i < result.cols; ++i) {
              rotation_180_outputs.push(i);
            }
          }
          try {
            const response = await GlobalData.getInstance()
              .getCurrentClient()
              ?.customConnection.setVideoWallConfig(
                rotation_180_outputs,
                screen_mode.value == 0 ? result.rows : result.cols,
                screen_mode.value == 0 ? result.cols : result.rows,
                screen_mode.value == 0 ? 0 : 90
              );
            if (response) {
              success = response.success;
            }
          } catch (e) {
            console.error(e);
          }

          show_dialog.value = false;
        } catch {}

        $q.notify({
          color: success ? "positive" : "negative",
          icon: success ? "done" : "warning",
          message:
            $t.t("apply") + (success ? $t.t("success") : $t.t("fail")) + "!",
          position: "top",
          timeout: 1500,
        });
        loading.value = false;
      },
      setSpliceIndex(device_index: number, splice_index: number) {
        let items = [];
        for (let i = 0; i < 25; ++i) {
          items.push({
            label: (i + 1).toString(),
            value: i.toString(),
          });
        }
        $q.dialog({
          title: $t.t("set splice index"),
          message: $t.t("please select new index") + ":",
          options: {
            type: "radio",
            model: splice_index.toString(),
            items: items,
            isValid: (v) => v != splice_index.toString(),
          },
          ok: {
            label: $t.t("ok"),
            noCaps: true,
            flat: true,
          },
          cancel: {
            label: $t.t("cancel"),
            noCaps: true,
            flat: true,
          },
        }).onOk(async (data) => {
          const temp = parseInt(data);
          let success = false;
          if (!isNaN(temp)) {
            const response = await GlobalData.getInstance()
              .getCurrentClient()
              ?.setOutputBoardSpliceIndex(device_index, temp);
            if (response) {
              success = response.success;
              if (success) {
                const item = outputs.value.find(
                  (e) => e && e.index == response.device_index
                );
                if (item) {
                  item.output_index = response.splice_index;
                }
              }
            }
          }
          $q.notify({
            color: success ? "positive" : "negative",
            icon: success ? "done" : "warning",
            message:
              $t.t("set splice index") +
              $t.t(success ? "success" : "failed") +
              "!",
            position: "top",
            timeout: 2500,
          });
        });
      },
    };
  },
});
</script>
