<script setup lang="ts">
import { computed, onMounted, onUnmounted, ref, useTemplateRef, watch } from 'vue';
import { message } from 'ant-design-vue';
import qs from 'qs';

import { useRequest } from '@/hooks/request';
import { useViewVisible } from '@/hooks/view-visible';
import { updateGroupModuleInfo } from '@/api';

import SvgIcon from '../SvgIcon.vue';

import { getVisual2DMsgType, visual2DEditorPageUrl, Visual2DMsgType } from '.';

import type { DeviceGroupTree, GroupModuleInfo, IframeMsg } from '@/types';

interface Props {
  info: GroupModuleInfo;
  deviceList?: DeviceGroupTree[];
}

const props = defineProps<Props>();

const emit = defineEmits<{
  close: [];
}>();

const { visible, showView, hideView } = useViewVisible();
const { handleRequest } = useRequest();
const iframeRef = useTemplateRef('editorIframe');
const isIframeLoaded = ref(false);

const iframeUrl = computed(() => {
  const { leId, moduleType } = props.info;

  return `${visual2DEditorPageUrl}?${qs.stringify({
    id: leId,
    moduleType,
  })}`;
});

onMounted(() => {
  window.addEventListener('message', handleIframeMsg);
});

onUnmounted(() => {
  window.removeEventListener('message', handleIframeMsg);
});

watch(visible, () => {
  if (visible.value && isIframeLoaded.value) {
    // 刷新画布
  }
});

const handleIframeMsg = (e: MessageEvent<IframeMsg>) => {
  const { msgType } = e.data;

  if (msgType === getVisual2DMsgType(Visual2DMsgType.EditLoaded)) {
    isIframeLoaded.value = true;
    sendDeviceData();
  } else if (msgType === getVisual2DMsgType(Visual2DMsgType.SendDeviceIds)) {
    updateGroupModule(e.data.deviceIds);
  } else if (msgType === getVisual2DMsgType(Visual2DMsgType.SaveModuleFailed)) {
    hideExitView();

    if (e.data.errMsg) {
      message.error(e.data.errMsg);
    }
  } else if (msgType === getVisual2DMsgType(Visual2DMsgType.CloseEditor)) {
    hideExitView();
    setTimeout(hideView, 1200);
  }
};

const sendDeviceData = () => {
  if (props.deviceList) {
    const msg: IframeMsg = {
      msgType: getVisual2DMsgType(Visual2DMsgType.SendDeviceData),
      deviceList: JSON.parse(JSON.stringify(props.deviceList)),
    };

    iframeRef.value?.contentWindow?.postMessage(msg, '*');
  }
};

const updateGroupModule = (deviceIds: string) => {
  handleRequest(async () => {
    await updateGroupModuleInfo({
      id: props.info.id,
      deviceIds,
    });
  });
};

const handleClose = () => {
  isIframeLoaded.value = false;
  emit('close');
};

const { visible: exitVisible, showView: showExitView, hideView: hideExitView } = useViewVisible();
const isExitLoading = ref(false);

const handleNoSave = () => {
  hideExitView();
  hideView();
};

const handleSave = () => {
  const msg: IframeMsg = {
    msgType: getVisual2DMsgType(Visual2DMsgType.SaveModule),
  };

  iframeRef.value?.contentWindow?.postMessage(msg, '*');
  isExitLoading.value = true;
};

const handleExitClose = () => {
  isExitLoading.value = false;
};

defineExpose({
  showView,
  hideView,
});
</script>

<template>
  <AModal
    v-model:open="visible"
    wrap-class-name="visual-2d-editor-modal"
    width="100%"
    centered
    :closable="false"
    :mask-closable="false"
    :keyboard="false"
    :footer="null"
    :after-close="handleClose"
    destroy-on-close
  >
    <SvgIcon name="close" @click="showExitView" />
    <iframe ref="editorIframe" :src="iframeUrl"></iframe>
    <ASpin v-if="!isIframeLoaded" class="center-loading visual-2d-editor-loading" :spinning="true" />
  </AModal>
  <AModal
    v-model:open="exitVisible"
    :title="$t('common.exitEdit')"
    wrap-class-name="hvac-modal visual-2d-editor-exit-modal"
    :width="400"
    :z-index="1001"
    centered
    :mask-closable="false"
    :after-close="handleExitClose"
  >
    <div>{{ $t('realTimeMonitor.saveChangesPrompt', { name: info.groupName }) }}</div>
    <template #footer>
      <AButton class="float-left" danger :disabled="isExitLoading" @click="handleNoSave">
        {{ $t('common.noSave') }}
      </AButton>
      <AButton :disabled="isExitLoading" @click="hideExitView">{{ $t('common.cancel') }}</AButton>
      <AButton type="primary" :loading="isExitLoading" @click="handleSave">{{ $t('common.save') }}</AButton>
    </template>
  </AModal>
</template>

<style lang="scss">
.visual-2d-editor-modal {
  padding: 32px;

  .svg-icon-close {
    position: absolute;
    top: 8px;
    right: 12px;
    padding: 4px;
    font-size: 16px;
    color: rgb(255 255 255 / 75%);
    cursor: pointer;
    transition:
      color 0.2s,
      background-color 0.2s;

    &:hover {
      color: #fff;
      background-color: rgb(255 255 255 / 12%);
    }
  }

  .ant-modal {
    max-width: 1700px;
  }

  .ant-modal,
  .ant-modal > div,
  .ant-modal-content {
    height: 812px;
  }

  .ant-modal-content {
    padding: 0;
  }

  .ant-modal-body,
  iframe {
    width: 100%;
    height: 100%;
  }

  iframe {
    overflow: hidden;
    background: transparent;
    border: none;
    border-radius: 8px;
  }

  .visual-2d-editor-loading {
    background-color: #fff;
    border-radius: 8px;
  }
}

.visual-2d-editor-exit-modal {
  .ant-modal-footer .ant-btn + .ant-btn:not(.ant-dropdown-trigger) {
    margin-inline-start: 16px;
  }
}
</style>
