<script setup lang="ts">
/**
 * MindMapCanvas - 思维导图画布组件
 * 
 * 基于四层架构实现：
 * - Graph Model（数据模型）
 * - Layout Engine（布局引擎）
 * - Canvas Renderer（渲染层）
 * - Interaction System（交互系统）
 */

import { ref, onMounted, watch, computed } from 'vue'
import { useMindMap } from './useMindMap'
import type { LayoutType, SerializedGraph } from './core/types'

// Props
const props = defineProps<{
  modelValue?: string | SerializedGraph
  layoutType?: LayoutType
  readonly?: boolean
}>()

// Emits
const emit = defineEmits<{
  (e: 'update:modelValue', value: string): void
  (e: 'nodeClick', nodeId: string): void
  (e: 'nodeDoubleClick', nodeId: string): void
  (e: 'layoutChange', type: LayoutType): void
}>()

// Refs
const canvasContainer = ref<HTMLDivElement>()
const canvasRef = ref<HTMLCanvasElement>()

// 使用组合式函数
const {
  graph,
  layoutType,
  renderer,
  interaction,
  initCanvas,
  applyLayout,
  addNode,
  removeNode,
  updateNodeLabel,
  toggleCollapse,
  exportData,
  importData,
  fitView,
  zoomIn,
  zoomOut,
  resetZoom
} = useMindMap({
  layoutType: props.layoutType
})

// 布局选项
const layoutOptions = [
  { label: '思维导图', key: 'radial-mindmap' },
  { label: '逻辑树', key: 'logic-tree' },
  { label: '鱼骨图', key: 'fishbone' },
  { label: '树形图', key: 'tree' },
  { label: '组织结构图', key: 'org-chart' },
  { label: '横向时间轴', key: 'timeline-horizontal' },
  { label: '纵向时间轴', key: 'timeline-vertical' },
  { label: '力导向图', key: 'force-directed' }
]

// 当前布局标签
const currentLayoutLabel = computed(() => {
  const option = layoutOptions.find(o => o.key === layoutType.value)
  return option?.label || '思维导图'
})

// 初始化
onMounted(() => {
  if (canvasRef.value) {
    const needsFitView = initCanvas(canvasRef.value)
    
    // 加载初始数据
    if (props.modelValue) {
      try {
        const data = typeof props.modelValue === 'string' 
          ? JSON.parse(props.modelValue) 
          : props.modelValue
        importData(data)
      } catch (e) {
        console.error('Failed to load mindmap data:', e)
      }
    } else if (needsFitView) {
      // 新建时适应画布
      setTimeout(() => fitView(), 100)
    }
    
    // 绑定交互事件
    if (interaction.value) {
      interaction.value.on('node:click', (e) => {
        emit('nodeClick', e.nodeId!)
      })
      
      interaction.value.on('node:dblclick', (e) => {
        emit('nodeDoubleClick', e.nodeId!)
      })
    }
    
    setTimeout(() => fitView(), 100)
  }
})

// 监听数据变化
watch(() => props.modelValue, (val) => {
  if (val) {
    try {
      const data = typeof val === 'string' ? JSON.parse(val) : val
      importData(data)
    } catch (e) {
      console.error('Failed to load mindmap data:', e)
    }
  }
}, { deep: true })

// 监听布局类型变化
watch(() => props.layoutType, (val) => {
  if (val && val !== layoutType.value) {
    applyLayout(val)
  }
})

// 保存数据
function saveData(): void {
  const data = exportData()
  emit('update:modelValue', JSON.stringify(data))
}

// 切换布局
function switchLayout(type: LayoutType): void {
  applyLayout(type)
  emit('layoutChange', type)
  saveData()
}

// 暴露方法给父组件
defineExpose({
  applyLayout,
  addNode,
  removeNode,
  updateNodeLabel,
  toggleCollapse,
  exportData,
  importData,
  fitView,
  zoomIn,
  zoomOut,
  resetZoom
})
</script>

<template>
  <div class="mind-map-container" ref="canvasContainer">
    <!-- 工具栏 -->
    <div class="toolbar">
      <div class="toolbar-left">
        <span class="layout-label">{{ currentLayoutLabel }}</span>
      </div>
      
      <div class="toolbar-center">
        <div class="layout-switcher">
          <button
            v-for="option in layoutOptions"
            :key="option.key"
            :class="['layout-btn', { active: layoutType === option.key }]"
            @click="switchLayout(option.key as LayoutType)"
          >
            {{ option.label }}
          </button>
        </div>
      </div>
      
      <div class="toolbar-right">
        <button class="tool-btn" @click="zoomIn" title="放大">+</button>
        <button class="tool-btn" @click="zoomOut" title="缩小">-</button>
        <button class="tool-btn" @click="fitView" title="适应">Fit</button>
        <button class="tool-btn" @click="resetZoom" title="重置">Reset</button>
      </div>
    </div>
    
    <!-- Canvas -->
    <div class="canvas-wrapper">
      <canvas ref="canvasRef" class="mind-map-canvas"></canvas>
    </div>
  </div>
</template>

<style scoped>
.mind-map-container {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  background: #f8fafc;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  overflow: hidden;
}

.toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 16px;
  background: #ffffff;
  border-bottom: 1px solid #e2e8f0;
  gap: 16px;
}

.toolbar-left {
  display: flex;
  align-items: center;
  gap: 8px;
}

.layout-label {
  font-size: 14px;
  font-weight: 500;
  color: #0f766e;
}

.toolbar-center {
  flex: 1;
  display: flex;
  justify-content: center;
}

.layout-switcher {
  display: flex;
  gap: 4px;
  background: #f1f5f9;
  padding: 4px;
  border-radius: 6px;
}

.layout-btn {
  padding: 6px 12px;
  font-size: 13px;
  color: #64748b;
  background: transparent;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.2s;
}

.layout-btn:hover {
  color: #334155;
  background: #e2e8f0;
}

.layout-btn.active {
  color: #ffffff;
  background: #0f766e;
}

.toolbar-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

.tool-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  color: #64748b;
  background: #f1f5f9;
  border: none;
  border-radius: 6px;
  cursor: pointer;
}

.tool-btn:hover {
  color: #0f766e;
  background: #e2e8f0;
}

.canvas-wrapper {
  flex: 1;
  position: relative;
  overflow: hidden;
}

.mind-map-canvas {
  display: block;
  width: 100%;
  height: 100%;
}
</style>
