<script setup lang="ts">
import { getSceneById, pushSceneById, saveSceneById } from '@api/scene';
import { EditorService } from '@core/editor.service';
import { useViewState } from '@core/useViewState';
import { decodeTextFile, downloadFile, selectFile, textToBlob } from '@core/utils';
import { message, Modal } from 'ant-design-vue';
import { computed, watch } from 'vue';
import { ref } from 'vue';
import { onMounted, provide, shallowRef } from 'vue';
import { useI18n } from 'vue-i18n';

const EDITOR_KEY = Symbol('editor-key');

type Props = {
  id: string;
};
const props = defineProps<Props>();

const { t } = useI18n();

//#region 接口
const readScene = async () => {
  const res = await getSceneById(props.id);
  title.value = res?.label ?? '';
  editor.value?.load(res?.json, editable.value);
};

const saveScene = async () => {
  const json = editor.value?.save();
  if (!json) return Promise.reject('无法获取场景数据');
  const res = await saveSceneById(props.id, json);
  if (!res) return Promise.reject('保存失败');

  // 保存成功后重置历史记录状态，表示当前场景已保存
  if (editor.value?.store) {
    editor.value.store.historyIndex = undefined;
    editor.value.store.histories = [];
  }

  message.success(t('场景保存成功'));
  return Promise.resolve();
};

const pushScene = async () => {
  const res = await pushSceneById(props.id);
  if (!res) return Promise.reject();
  message.success(t('场景推送成功'));
  return Promise.resolve();
};

//#endregion

const title = ref<string>('');

// 监听标题变化，动态更新页面标题
onMounted(() => {
  document.title = '场景编辑器';
});

watch(
  () => props.id,
  async () => {
    await readScene();
    // 在场景加载完成后自动保存和恢复视图状态
    await handleAutoSaveAndRestoreViewState();
  },
  { immediate: true, flush: 'post' },
);

const container = shallowRef<HTMLDivElement>();
const editor = shallowRef<EditorService>();
provide(EDITOR_KEY, editor);
onMounted(() => {
  editor.value = new EditorService(container.value!);
});

const editable = ref<boolean>(false);
watch(editable, (v) => editor.value?.setState(v));

const toPush = () => {
  Modal.confirm({
    class: 'confirm',
    title: t('是否保存并推送该场景文件？'),
    content: t('推送前会先保存当前场景的所有修改。'),
    centered: true,
    cancelText: t('取消'),
    okText: t('保存并推送'),
    onOk: async () => {
      try {
        await saveScene();
        await pushScene();
      } catch (error) {
        console.error('保存或推送失败:', error);
      }
    },
  });
};

const importScene = async () => {
  const file = await selectFile('.scene');
  if (!file?.size) return;
  const json = await decodeTextFile(file);
  editor.value?.load(json, editable.value);
};
const exportScene = () => {
  const json = editor.value?.save();
  if (!json) return;
  const blob = textToBlob(json);
  if (!blob?.size) return;
  const url = URL.createObjectURL(blob);
  downloadFile(url, `${title.value || 'unknown'}.scene`);
  URL.revokeObjectURL(url);
};

const show = ref<boolean>(true);
const current = ref<{ type: 'robot' | 'point' | 'line' | 'area'; id: string }>();
watch(
  () => editor.value?.selected.value[0],
  (v) => {
    const pen = editor.value?.getPenById(v);
    if (pen?.id) {
      current.value = { type: <'point' | 'line' | 'area'>pen.name, id: pen.id };
      return;
    }
    if (current.value?.type === 'robot') return;
    current.value = undefined;
  },
);
const isRobot = computed(() => current.value?.type === 'robot');
const isPoint = computed(() => current.value?.type === 'point');
const isRoute = computed(() => current.value?.type === 'line');
const isArea = computed(() => current.value?.type === 'area');

const selectRobot = (id: string) => {
  current.value = { type: 'robot', id };
  editor.value?.inactive();
};

// 视图状态管理
const { saveViewState, autoSaveAndRestoreViewState, isSaving } = useViewState();

// 保存当前视图状态
const handleSaveViewState = async () => {
  if (!editor.value) return;

  try {
    await saveViewState(editor.value, props.id);
    message.success('视图状态保存成功');
  } catch {
    message.error('视图状态保存失败');
  }
};

// 自动保存和恢复视图状态
const handleAutoSaveAndRestoreViewState = async () => {
  if (!editor.value) return;

  await autoSaveAndRestoreViewState(editor.value, props.id);
};
</script>

<template>
  <a-layout class="full">
    <a-layout-header class="p-16" style="height: 64px">
      <a-flex justify="space-between" align="center">
        <a-typography-text class="title">{{ title }} --场景编辑</a-typography-text>
        <a-space align="center">
          <a-button type="primary" :loading="isSaving" @click="handleSaveViewState"> 保存比例 </a-button>
          <a-button v-if="editable" class="warning" @click="editable = false">
            <i class="icon exit size-18 mr-8" />
            <span>{{ $t('退出编辑器') }}</span>
          </a-button>
          <a-button v-else type="primary" @click="editable = true">
            <i class="icon edit size-18 mr-8" />
            <span>{{ $t('启用编辑器') }}</span>
          </a-button>
          <a-button @click="toPush">{{ $t('推送') }}</a-button>
          <a-button @click="importScene">{{ $t('导入') }}</a-button>
          <a-button @click="exportScene">{{ $t('导出') }}</a-button>
        </a-space>
      </a-flex>
    </a-layout-header>

    <a-layout class="p-16">
      <a-layout-sider :width="320">
        <a-tabs type="card">
          <a-tab-pane key="1" :tab="$t('机器人')">
            <RobotGroups
              v-if="editor"
              :token="EDITOR_KEY"
              :sid="id"
              :editable="editable"
              :current="current?.id"
              @change="selectRobot"
              show-group-edit
            />
          </a-tab-pane>
          <a-tab-pane key="2" :tab="$t('库区')">
            <PenGroups v-if="editor" :token="EDITOR_KEY" :current="current?.id" only-area1 />
          </a-tab-pane>
          <a-tab-pane key="3" :tab="$t('高级组')">
            <PenGroups v-if="editor" :token="EDITOR_KEY" :current="current?.id" />
          </a-tab-pane>
        </a-tabs>
      </a-layout-sider>
      <a-layout-content>
        <div ref="container" class="editor-container full"></div>
      </a-layout-content>
    </a-layout>
  </a-layout>

  <div v-if="editable" class="toolbar-container">
    <EditorToolbar v-if="editor" :token="EDITOR_KEY" :id="id" />
  </div>

  <template v-if="current?.id">
    <a-float-button style="top: 80px; right: 16px" shape="square" @click="show = !show">
      <template #icon><i class="icon detail" /></template>
    </a-float-button>
    <div v-if="show" class="card-container">
      <RobotDetailCard v-if="isRobot" :token="EDITOR_KEY" :current="current.id" />

      <template v-if="isPoint">
        <PointEditCard v-if="editable" :token="EDITOR_KEY" :id="current.id" />
        <PointDetailCard v-else :token="EDITOR_KEY" :current="current.id" />
      </template>
      <template v-if="isRoute">
        <RouteEditCard v-if="editable" :token="EDITOR_KEY" :id="current.id" />
        <RouteDetailCard v-else :token="EDITOR_KEY" :current="current.id" />
      </template>
      <template v-if="isArea">
        <AreaEditCard v-if="editable" :token="EDITOR_KEY" :id="current.id" />
        <AreaDetailCard v-else :token="EDITOR_KEY" :current="current.id" />
      </template>
    </div>
  </template>
</template>

<style scoped lang="scss">
.editor-container {
  background-color: transparent !important;
}

.toolbar-container {
  position: fixed;
  bottom: 40px;
  left: 50%;
  z-index: 100;
  transform: translateX(-50%);
}

.card-container {
  position: fixed;
  top: 80px;
  right: 64px;
  z-index: 100;
  width: 320px;
  height: calc(100% - 96px);
  overflow: visible;
  pointer-events: none;

  & > * {
    pointer-events: all;
  }
}
</style>
