<template>
  <div
    class="window_class window_flag"
    :class="
      (selected ? 'window_selected' : 'window_normal') +
      ' ' +
      (focused ? 'top' : '')
    "
    @click="onClick"
    @mousedown="onMouseDown"
    @mousemove="onMouseMove"
    @mouseleave="onMouseLeave"
    @mouseup="onMouseLeave"
  >
    <q-popup-proxy context-menu>
      <q-popup-proxy context-menu />
      <q-list>
        <q-item
          clickable
          v-close-popup
          @click="$emit('close_this_window', $props.window.window_id)"
        >
          <q-item-section> {{ $t("close this window") }} </q-item-section>
        </q-item>
        <q-item
          clickable
          v-close-popup
          @click="$emit('close_other_windows', $props.window.window_id)"
        >
          <q-item-section>
            {{ $t("close other windows") }}
          </q-item-section>
        </q-item>
        <q-item
          clickable
          v-close-popup
          @click="$emit('close_all_windows', $props.window.window_id)"
        >
          <q-item-section> {{ $t("close all windwos") }} </q-item-section>
        </q-item>
      </q-list>
    </q-popup-proxy>
    <div class="title_bar full-width">
      <q-icon :name="getItemIcon(signal_source.window_type)" />
      <span>{{ signal_source.name }}</span>
    </div>

    <div
      v-if="selected && can_resize"
      class="resize_div absolute_up"
      ref="resize_up"
      @mousedown="onMouseDown"
      @mousemove="(evt) => onResizeMouseMove(evt, flags.up_flag)"
      @mouseleave="onMouseLeave"
      @mouseup="onMouseLeave"
    ></div>
    <div
      v-if="selected && can_resize"
      class="resize_div absolute_down"
      ref="resize_down"
      @mousedown="onMouseDown"
      @mousemove="(evt) => onResizeMouseMove(evt, flags.down_flag)"
      @mouseleave="onMouseLeave"
      @mouseup="onMouseLeave"
    ></div>
    <div
      v-if="selected && can_resize"
      class="resize_div absolute_left"
      ref="resize_left"
      @mousedown="onMouseDown"
      @mousemove="(evt) => onResizeMouseMove(evt, flags.left_flag)"
      @mouseleave="onMouseLeave"
      @mouseup="onMouseLeave"
    ></div>
    <div
      v-if="selected && can_resize"
      class="resize_div absolute_right"
      ref="resize_right"
      @mousedown="onMouseDown"
      @mousemove="(evt) => onResizeMouseMove(evt, flags.right_flag)"
      @mouseleave="onMouseLeave"
      @mouseup="onMouseLeave"
    ></div>
    <div
      v-if="selected && can_resize"
      class="resize_div absolute_left_up"
      ref="resize_left_up"
      @mousedown="onMouseDown"
      @mousemove="
        (evt) => onResizeMouseMove(evt, flags.up_flag | flags.left_flag)
      "
      @mouseleave="onMouseLeave"
      @mouseup="onMouseLeave"
    ></div>
    <div
      v-if="selected && can_resize"
      class="resize_div absolute_right_up"
      ref="resize_right_up"
      @mousedown="onMouseDown"
      @mousemove="
        (evt) => onResizeMouseMove(evt, flags.up_flag | flags.right_flag)
      "
      @mouseleave="onMouseLeave"
      @mouseup="onMouseLeave"
    ></div>
    <div
      v-if="selected && can_resize"
      class="resize_div absolute_left_down"
      ref="resize_left_down"
      @mousedown="onMouseDown"
      @mousemove="
        (evt) => onResizeMouseMove(evt, flags.down_flag | flags.left_flag)
      "
      @mouseleave="onMouseLeave"
      @mouseup="onMouseLeave"
    ></div>
    <div
      v-if="selected && can_resize"
      class="resize_div absolute_right_down"
      ref="resize_right_down"
      @mousedown="onMouseDown"
      @mousemove="
        (evt) => onResizeMouseMove(evt, flags.down_flag | flags.right_flag)
      "
      @mouseleave="onMouseLeave"
      @mouseup="onMouseLeave"
    ></div>
  </div>
</template>

<style scoped>
.window_class {
}

.window_flag {
}

.window_selected {
  outline-style: dashed;
  outline-color: #166fab;
}

.window_normal {
  border: 1px solid #166fab;
}

.title_bar {
  border: 1px solid black;
}

.top {
  z-index: 1;
}

.resize_div {
  background: gray;
  width: 32px;
  height: 32px;
}

.absolute_up {
  position: absolute;
  top: -16px;
  left: calc(50% - 16px);
}

.absolute_down {
  position: absolute;
  bottom: -16px;
  left: calc(50% - 16px);
}

div.absolute_up,
div.absolute_down {
  cursor: s-resize;
}

.absolute_left {
  position: absolute;
  top: calc(50% - 16px);
  left: -16px;
}

.absolute_right {
  position: absolute;
  top: calc(50% - 16px);
  right: -16px;
}

div.absolute_left,
div.absolute_right {
  cursor: w-resize;
}

.absolute_left_up {
  position: absolute;
  top: -16px;
  left: -16px;
}

.absolute_left_down {
  position: absolute;
  bottom: -16px;
  left: -16px;
}

.absolute_right_up {
  position: absolute;
  top: -16px;
  right: -16px;
}

.absolute_right_down {
  position: absolute;
  bottom: -16px;
  right: -16px;
}

div.absolute_left_up,
div.absolute_right_down {
  cursor: se-resize;
}

div.absolute_right_up,
div.absolute_left_down {
  cursor: ne-resize;
}
</style>

<script lang="ts">
import { Common } from "src/common/Common";
import EventBus, { EventNamesDefine } from "src/common/EventBus";
import GlobalData from "src/common/GlobalData";
import { defineComponent, ref, watch, onUnmounted } from "vue";
import { useStore } from "src/store";

class _Flags {
  get up_flag() {
    return 0x0001;
  }
  get down_flag() {
    return 0x0002;
  }
  get left_flag() {
    return 0x0004;
  }
  get right_flag() {
    return 0x0008;
  }
}

export default defineComponent({
  name: "ComponentWindow",

  components: {},
  props: {
    signal_source_table_uuid: {
      type: String,
      required: true,
    },
    window: {
      type: Object,
      required: true,
    },
  },
  emits: [
    "reset_geometry_offset",
    "commit_geometry",
    "close_this_window",
    "close_other_windows",
    "close_all_windows",
    "window_fouse_in",
  ],
  setup(props, { emit }) {
    const $store = useStore();

    const signal_source = ref(
      GlobalData.getInstance().getSignalSource(props.signal_source_table_uuid)
    );

    let selected = ref(false);
    let focused = ref(false);
    let can_move = ref(true);
    let can_resize = ref(true);

    const onUnSelectAllWindows = () => {
      selected.value = false;
      focused.value = false;
    };

    const onUnFocusAllWindows = () => {
      focused.value = false;
    };

    EventBus.getInstance().on(
      EventNamesDefine.UnSelectAllWindows,
      onUnSelectAllWindows
    );

    EventBus.getInstance().on(
      EventNamesDefine.UnFocusAllWindows,
      onUnFocusAllWindows
    );

    onUnmounted(() => {
      EventBus.getInstance().removeListener(
        EventNamesDefine.UnSelectAllWindows,
        onUnSelectAllWindows
      );
    });

    watch(
      () => props.window.window_state,
      (newValue, oldValue) => {
        if (newValue) {
          let old = selected.value;
          if (newValue.focus) {
            EventBus.getInstance().emit(EventNamesDefine.UnFocusAllWindows);
          }
          focused.value = newValue.focus;
          selected.value = old;
        }
      }
    );

    let mouse_down_flag = false;
    let mouse_last_pos_x = 0;
    let mouse_last_pos_y = 0;

    const cleanMouseDownFlag = () => {
      mouse_down_flag = false;
      mouse_last_pos_x = 0;
      mouse_last_pos_y = 0;
    };

    const flags = new _Flags();

    return {
      signal_source,
      selected,
      focused,
      can_move,
      can_resize,
      flags,

      onClick(evt: PointerEvent) {
        if (selected.value != true) {
          EventBus.getInstance().emit(EventNamesDefine.UnSelectAllWindows);
          selected.value = true;
          focused.value = true;
          emit("window_fouse_in", props.window.window_id);
        }
      },
      onMouseDown(evt: MouseEvent) {
        if (selected.value) {
          if (evt.button == 0) {
            mouse_down_flag = true;
            mouse_last_pos_x = evt.x;
            mouse_last_pos_y = evt.y;
          }
        }
      },
      onMouseMove(evt: MouseEvent) {
        if (can_move.value && mouse_down_flag && selected.value) {
          emit(
            "reset_geometry_offset",
            props.window,
            evt.x - mouse_last_pos_x,
            evt.y - mouse_last_pos_y,
            0,
            0
          );

          mouse_last_pos_x = evt.x;
          mouse_last_pos_y = evt.y;
        }
      },

      onResizeMouseDown(evt: MouseEvent) {},

      onResizeMouseMove(evt: MouseEvent, dir: number) {
        if (can_resize.value && mouse_down_flag && selected.value) {
          const h = evt.x - mouse_last_pos_x;
          const v = evt.y - mouse_last_pos_y;
          let x_offset = 0;
          let y_offset = 0;
          let width_offset = 0;
          let height_offset = 0;
          if (dir & flags.up_flag) {
            y_offset += v;
            height_offset -= v;
          }
          if (dir & flags.down_flag) {
            height_offset += v;
          }
          if (dir & flags.left_flag) {
            x_offset += h;
            width_offset -= h;
          }
          if (dir & flags.right_flag) {
            width_offset += h;
          }
          emit(
            "reset_geometry_offset",
            props.window,
            x_offset,
            y_offset,
            width_offset,
            height_offset
          );

          mouse_last_pos_x = evt.x;
          mouse_last_pos_y = evt.y;
        }
      },

      cleanMouseDownFlag,
      onMouseLeave(evt: MouseEvent) {
        if (selected.value && mouse_down_flag) {
          cleanMouseDownFlag();
          emit("commit_geometry", props.window);
        }
      },

      onMouseUp(evt: MouseEvent) {
        if (selected.value && mouse_down_flag) {
          cleanMouseDownFlag();
          emit("commit_geometry", props.window);
        }

        if (!focused) {
          emit("window_fouse_in", props.window.window_id);
        }
      },

      getItemIcon(item_type: string) {
        return Common.getSignalSourceIcon(item_type);
      },
    };
  },
});
</script>
