<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: 50vw">
      <q-form @submit="onSubmit">
        <q-card-section class="q-ma-none q-pa-sm">
          <div class="row">
            <div class="col-auto text-h6">
              {{ $t("window rect") }}
            </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: 40vh; width: 50vw" class="scroll">
          <q-list>
            <q-item class="text-center text-h6">
              <q-item-section>
                <q-item-label>
                  <span>{{ $t("desktop width") }}: </span>
                  <span>
                    {{ screen_width }}
                  </span>
                  <span>{{ $t("px") }}</span>
                </q-item-label>
              </q-item-section>
              <q-item-section>
                <q-item-label>
                  <span>{{ $t("desktop height") }}: </span>
                  <span>
                    {{ screen_height }}
                  </span>
                  <span>{{ $t("px") }}</span>
                </q-item-label>
              </q-item-section>
            </q-item>
            <q-separator />
            <q-item>
              <q-item-section>
                <q-item>
                  <q-item-section avatar>
                    <span class="q-mb-md">{{ $t("X") }}:</span>
                  </q-item-section>
                  <q-item-section>
                    <q-input
                      autofocus
                      type="number"
                      min="0"
                      v-model="window_rect.x"
                      :rules="[
                        (val) =>
                          (val != null &&
                            val != undefined &&
                            val.toString().length > 0) ||
                          $t('Please type something'),
                        (val) =>
                          parseInt(val) >= 0 ||
                          $t('the number must be greater than 0'),
                      ]"
                      lazy-rules
                    >
                      <template v-slot:append>
                        <span class="input_append">{{ $t("px") }}</span>
                      </template>
                    </q-input>
                  </q-item-section>
                </q-item>
              </q-item-section>

              <q-item-section>
                <q-item>
                  <q-item-section avatar>
                    <span class="q-mb-md">{{ $t("Y") }}:</span>
                  </q-item-section>
                  <q-item-section>
                    <q-input
                      type="number"
                      min="0"
                      v-model="window_rect.y"
                      :rules="[
                        (val) =>
                          (val != null &&
                            val != undefined &&
                            val.toString().length > 0) ||
                          $t('Please type something'),
                        (val) =>
                          parseInt(val) >= 0 ||
                          $t('the number must be greater than 0'),
                      ]"
                      lazy-rules
                    >
                      <template v-slot:append>
                        <span class="input_append">{{ $t("px") }}</span>
                      </template>
                    </q-input>
                  </q-item-section>
                </q-item>
              </q-item-section>
            </q-item>
            <q-item>
              <q-item-section>
                <q-item>
                  <q-item-section avatar>
                    <span class="q-mb-md">{{ $t("width") }}:</span>
                  </q-item-section>
                  <q-item-section>
                    <q-input
                      type="number"
                      min="1"
                      v-model="window_rect.width"
                      :rules="[
                        (val) =>
                          (val != null &&
                            val != undefined &&
                            val.toString().length > 0) ||
                          $t('Please type something'),
                        (val) =>
                          parseInt(val) >= 1 ||
                          $t('the number must be greater than 1'),
                      ]"
                      lazy-rules
                    >
                      <template v-slot:append>
                        <span class="input_append">{{ $t("px") }}</span>
                      </template>
                    </q-input>
                  </q-item-section>
                </q-item>
              </q-item-section>

              <q-item-section>
                <q-item>
                  <q-item-section avatar>
                    <span class="q-mb-md">{{ $t("height") }}:</span>
                  </q-item-section>
                  <q-item-section>
                    <q-input
                      type="number"
                      min="1"
                      v-model="window_rect.height"
                      :rules="[
                        (val) =>
                          (val != null &&
                            val != undefined &&
                            val.toString().length > 0) ||
                          $t('Please type something'),
                        (val) =>
                          parseInt(val) >= 1 ||
                          $t('the number must be greater than 1'),
                      ]"
                      lazy-rules
                    >
                      <template v-slot:append>
                        <span class="input_append">{{ $t("px") }}</span>
                      </template>
                    </q-input>
                  </q-item-section>
                </q-item>
              </q-item-section>
            </q-item>
          </q-list>
        </q-card-section>

        <q-separator />

        <q-card-actions align="right">
          <q-btn
            v-if="mod == 'sync'"
            :loading="loading"
            flat
            :label="$t('revert')"
            no-caps
            color="primary"
            @click="revertWindowRect"
          />
          <q-btn
            :loading="loading"
            flat
            :label="$t('Close')"
            no-caps
            :disable="loading"
            color="primary"
            v-close-popup
          />

          <q-btn
            v-if="mod == 'async'"
            ref="accept"
            flat
            :label="$t('Accept')"
            no-caps
            :loading="loading"
            type="submit"
            color="primary"
          />
        </q-card-actions>
      </q-form>
    </q-card>
  </q-dialog>
</template>

<style scoped>
.input_append {
  font-size: 1rem;
}
</style>

<script lang="ts">
import { defineComponent, ref, watch, computed, reactive } from "vue";
import { useStore } from "src/store";
import { useQuasar } from "quasar";
import { useI18n } from "vue-i18n";
import GlobalData from "src/common/GlobalData";
import { SpecialVideoHelper } from "src/common/SpecialVideoHelper";

export default defineComponent({
  name: "ComponentWindowRectEditDialog",

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

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

    const screen_width = ref($store.state.device_screen_width);
    const screen_height = ref($store.state.device_screen_height);

    if ($store.state.isSpecialVideo()) {
      const screen_info = SpecialVideoHelper.getScreenInfo(
        $store.state.wall_col,
        $store.state.wall_row
      );
      screen_width.value = screen_info.screen_width;
      screen_height.value = screen_info.screen_height;
    }

    const window_rect = reactive({
      x: 0,
      y: 0,
      width: 0,
      height: 0,
      clean: function () {
        this.x = 0;
        this.y = 0;
        this.width = 0;
        this.height = 0;
      },

      formartNumber: function () {
        this.x = parseInt(<any>this.x);
        this.y = parseInt(<any>this.y);
        this.width = parseInt(<any>this.width);
        this.height = parseInt(<any>this.height);
      },

      getRealRect: function (screen_height: number, screen_width: number) {
        const result = {
          x: this.x,
          y: this.y,
          width: this.width,
          height: this.height,
        };

        result.x /= screen_width;
        result.y /= screen_height;
        result.width /= screen_width;
        result.height /= screen_height;
        return result;
      },
    });

    let back_window_rect = {
      x: 0,
      y: 0,
      width: 0,
      height: 0,
    };

    // async 为异步模式,不发送窗口指令,只返回坐标
    // sync 为同步模式,坐标修改后直接发送窗口指令,不返回任何数据
    const mod = ref("async"); // sync

    let _resolve: any = null;
    let _reject: any = null;

    const clean_promise = () => {
      try {
        if (_resolve && typeof _resolve == "function") {
          _resolve(null);
        } else if (_reject && typeof _reject == "function") {
          _reject(null);
        }
        _resolve = null;
        _reject = null;
      } catch {}
    };

    let current_window_id = 0;

    const sendSetWindowGeometryMessage = () => {
      if (mod.value == "async") {
        return;
      }
      const rect = window_rect.getRealRect(
        screen_height.value,
        screen_width.value
      );
      GlobalData.getInstance()
        .getCurrentClient()
        ?.setWindowGeometry(
          current_window_id,
          rect.x,
          rect.y,
          rect.width,
          rect.height
        );
    };

    watch(
      () => window_rect.x,
      () => {
        sendSetWindowGeometryMessage();
      }
    );

    watch(
      () => window_rect.y,
      () => {
        sendSetWindowGeometryMessage();
      }
    );
    watch(
      () => window_rect.width,
      () => {
        sendSetWindowGeometryMessage();
      }
    );
    watch(
      () => window_rect.height,
      () => {
        sendSetWindowGeometryMessage();
      }
    );

    return {
      show_dialog,
      loading,
      window_rect,
      screen_height,
      screen_width,
      mod,

      showDialog(window_id: number) {
        const window = $store.state.windows.find(
          (e) => e && e.window_id == window_id
        );
        if (window) {
          screen_width.value = $store.state.device_screen_width;
          screen_height.value = $store.state.device_screen_height;

          if ($store.state.isSpecialVideo()) {
            const screen_info = SpecialVideoHelper.getScreenInfo(
              $store.state.wall_col,
              $store.state.wall_row
            );
            screen_width.value = screen_info.screen_width;
            screen_height.value = screen_info.screen_height;
          }

          window_rect.clean();
          window_rect.x = Math.round(window.x * screen_width.value);
          window_rect.y = Math.round(window.y * screen_height.value);
          window_rect.width = Math.round(window.width * screen_width.value);
          window_rect.height = Math.round(window.height * screen_height.value);
          back_window_rect.x = window_rect.x;
          back_window_rect.y = window_rect.y;
          back_window_rect.width = window_rect.width;
          back_window_rect.height = window_rect.height;

          current_window_id = window_id;

          mod.value = "sync";
          show_dialog.value = true;
        } else {
          console.error("can't find window.", window_id);
        }
      },
      showDialogAsync(x: number, y: number, width: number, height: number) {
        return new Promise((resolve, reject) => {
          clean_promise();

          screen_width.value = $store.state.device_screen_width;
          screen_height.value = $store.state.device_screen_height;

          if ($store.state.isSpecialVideo()) {
            const screen_info = SpecialVideoHelper.getScreenInfo(
              $store.state.wall_col,
              $store.state.wall_row
            );
            screen_width.value = screen_info.screen_width;
            screen_height.value = screen_info.screen_height;
          }

          window_rect.clean();
          window_rect.x = Math.round(x);
          window_rect.y = Math.round(y);
          window_rect.width = Math.round(width);
          window_rect.height = Math.round(height);

          _resolve = resolve;
          _reject = reject;

          mod.value = "async";
          show_dialog.value = true;
        });
      },
      resetData() {
        show_dialog.value = false;
        loading.value = false;

        current_window_id = 0;
        back_window_rect = { x: 0, y: 0, height: 0, width: 0 };

        if (_reject) {
          try {
            _reject(null);
          } catch {}
        }
        _resolve = null;
        _reject = null;
      },
      onSubmit() {
        loading.value = true;

        window_rect.formartNumber();

        const resolve_data = () => {
          if (_resolve) {
            try {
              _resolve(window_rect);
            } catch {}
          }
          _resolve = null;
          _reject = null;
          loading.value = false;
          show_dialog.value = false;
        };

        if (
          window_rect.x + window_rect.width > screen_width.value ||
          window_rect.y + window_rect.height > screen_height.value
        ) {
          $q.dialog({
            title: $t.t("Warning"),
            message:
              $t.t(
                "set the window rectangle beyond the desktop rectangle, the window rectangle will be clipped, are you sure to use this window rectangle"
              ) + "?",
            ok: {
              label: $t.t("ok"),
              noCaps: true,
              flat: true,
            },
            cancel: {
              label: $t.t("cancel"),
              noCaps: true,
              flat: true,
            },
            persistent: true,
          })
            .onOk(() => resolve_data())
            .onCancel(() => (loading.value = false));
        } else {
          resolve_data();
        }
      },
      revertWindowRect() {
        window_rect.x = back_window_rect.x;
        window_rect.y = back_window_rect.y;
        window_rect.width = back_window_rect.width;
        window_rect.height = back_window_rect.height;
        sendSetWindowGeometryMessage();
      },
    };
  },
});
</script>
