import { defineStore } from 'pinia'
import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
import { PublicGroupConfigClass } from '@/packages/public/publicConfig'
import debounce from 'lodash/debounce'
import cloneDeep from 'lodash/cloneDeep'
import { defaultTheme, globalThemeJson } from '@/settings/chartThemes/index'
import { requestInterval, previewScaleType, requestIntervalUnit } from '@/settings/designSetting'
// 记录记录
import { useChartHistoryStore } from '@/store/modules/chartHistoryStore/chartHistoryStore'
// 全局设置
import { useSettingStore } from '@/store/modules/settingStore/settingStore'
import { HistoryActionTypeEnum, HistoryItemType, HistoryTargetTypeEnum } from '@/store/modules/chartHistoryStore/chartHistoryStore.d'
import { MenuEnum } from '@/enums/editPageEnum'
import { 
  getUUID,
  loadingStart,
  loadingFinish,
  loadingError,
  isString,
  isArray
} from '@/utils'
import {
  ChartEditStoreEnum,
  ChartEditStorage,
  ChartEditStoreType,
  EditCanvasType,
  MousePositionType,
  TargetChartType,
  RecordChartType,
  RequestGlobalConfigType,
  EditCanvasConfigType
} from './chartEditStore.d'

const chartHistoryStore = useChartHistoryStore()
const settingStore = useSettingStore()

// 编辑区域内容
export const useChartEditStore = defineStore({
  id: 'useChartEditStore',
  state: (): ChartEditStoreType => ({
    // 画布属性
    editCanvas: {
      // 编辑区域 Dom
      editLayoutDom: null,
      editContentDom: null,
      // 偏移量
      offset: 20,
      // 系统控制缩放
      scale: 1,
      // 用户控制的缩放
      userScale: 1,
      // 锁定缩放
      lockScale: false,
      // 初始化
      isCreate: false,
      // 拖拽中
      isDrag: false
    },
    // 右键菜单
    rightMenuShow: false,
    // 鼠标定位
    mousePosition: {
      startX: 0,
      startY: 0,
      x: 0,
      y: 0
    },
    // 目标图表
    targetChart: {
      hoverId: undefined,
      selectId: []
    },
    // 记录临时数据(复制等)
    recordChart: undefined,
    // -----------------------
    // 画布属性(需存储给后端)
    editCanvasConfig: {
      // 默认宽度
      width: 1920,
      // 默认高度
      height: 1080,
      // 色相
      hueRotate: 0,
      // 饱和度
      saturate: 1,
      // 对比度
      contrast: 1,
      // 亮度
      brightness: 1,
      // 透明度
      opacity: 1,
      // 变换(暂不更改)
      rotateZ: 0,
      rotateX: 0,
      rotateY: 0,
      skewX: 0,
      skewY: 0,
      // 默认背景色
      background: undefined,
      backgroundImage: undefined,
      // 是否使用纯颜色
      selectColor: true,
      // chart 主题色
      chartThemeColor: defaultTheme || 'dark',
      // 全局配置
      chartThemeSetting: globalThemeJson,
      // 预览方式
      previewScaleType: previewScaleType
    },
    // 数据请求处理(需存储给后端)
    requestGlobalConfig: {
      requestOriginUrl: '',
      requestInterval: requestInterval,
      requestIntervalUnit: requestIntervalUnit,
      requestParams: {
        Body: {
          "form-data": {},
          "x-www-form-urlencoded": {},
          json: '',
          xml: ''
        },
        Header: {},
        Params: {}
      }
    },
    // 图表数组(需存储给后端)
    componentList: []
  }),
  getters: {
    getMousePosition(): MousePositionType {
      return this.mousePosition
    },
    getRightMenuShow(): boolean {
      return this.rightMenuShow
    },
    getEditCanvas(): EditCanvasType {
      return this.editCanvas
    },
    getEditCanvasConfig(): EditCanvasConfigType {
      return this.editCanvasConfig
    },
    getTargetChart():TargetChartType {
      return this.targetChart
    },
    getRecordChart(): RecordChartType | undefined {
      return this.recordChart
    },
    getRequestGlobalConfig(): RequestGlobalConfigType {
      return this.requestGlobalConfig
    },
    getComponentList(): Array<CreateComponentType | CreateComponentGroupType> {
      return this.componentList
    },
    // 获取需要存储的数据项
    getStorageInfo(): ChartEditStorage {
      return {
        [ChartEditStoreEnum.EDIT_CANVAS_CONFIG]: this.getEditCanvasConfig,
        [ChartEditStoreEnum.COMPONENT_LIST]: this.getComponentList,
        [ChartEditStoreEnum.REQUEST_GLOBAL_CONFIG]: this.getRequestGlobalConfig
      }
    }
  },
  actions: {
    // * 设置 editCanvas 数据项
    setEditCanvas<T extends keyof EditCanvasType,  K extends EditCanvasType[T]>(key: T, value: K) {
      this.editCanvas[key] = value
    },
    // * 设置 editCanvasConfig(需保存后端) 数据项
    setEditCanvasConfig<T extends keyof EditCanvasConfigType,  K extends EditCanvasConfigType[T]>(key: T, value: K) {
      this.editCanvasConfig[key] = value
    },
    // * 设置右键菜单
    setRightMenuShow(value: boolean) {
      this.rightMenuShow = value
    },
    // * 设置目标数据 hover
    setTargetHoverChart(hoverId?:TargetChartType["hoverId"]) {
      this.targetChart.hoverId = hoverId
    },
    // * 设置目标数据 select
    setTargetSelectChart(selectId?: string | string[], push: boolean = false) {
      // 重复选中
      if(this.targetChart.selectId.find((e: string) => e === selectId)) return

      // 无 id 清空
      if(!selectId) {
        this.targetChart.selectId = []
        return
      }
      // 多选
      if(push) {
        // 字符串
        if(isString(selectId)) {
          this.targetChart.selectId.push(selectId)
          return
        }
        // 数组
        if(isArray(selectId)) {
          this.targetChart.selectId.push(...selectId)
          return
        }
      } else {
        // 字符串
        if(isString(selectId)) {
          this.targetChart.selectId = [selectId]
          return
        }
        // 数组
        if(isArray(selectId)) {
          this.targetChart.selectId = selectId
          return
        }
      }
    },
    // * 设置记录数据
    setRecordChart(item: RecordChartType | undefined) {
      this.recordChart = cloneDeep(item)
    },
    // * 设置鼠标位置
    setMousePosition(x?: number, y?: number, startX?: number, startY?: number): void {
      if (startX) this.mousePosition.startX = startX
      if (startY) this.mousePosition.startY = startY
      if (x) this.mousePosition.x = x
      if (y) this.mousePosition.y = y
    },
    // * 找到目标 id 数据下标位置(无则返回-1)
    fetchTargetIndex(id?: string): number {
      const targetId = id || this.getTargetChart.selectId.length && this.getTargetChart.selectId[0] || undefined
      if(!targetId) {
        loadingFinish()
        return -1
      }
      const index = this.componentList.findIndex(e => e.id === targetId)
      if (index === -1) {
        loadingError()
      }
      return index
    },
    // * 找到组数据的下标位置,id可为父级或子集数组(无则返回-1)
    fetchTargetGroupIndex(id?: string): number {
      const targetId = id || this.getTargetChart.selectId.length && this.getTargetChart.selectId[0] || undefined
      if(!targetId) {
        loadingFinish()
        return -1
      }
      const targetIndex = this.fetchTargetIndex(targetId)

      // 当前
      if(targetIndex !== -1) {
        return targetIndex
      } else {
        const length = this.getComponentList.length
        for(let i = 0; i < length; i++) {
          if(this.getComponentList[i].isGroup) {
            for(const cItem of (this.getComponentList[i] as CreateComponentGroupType).groupList) { 
              if(cItem.id === targetId) {
                return i
              }
            }
          }
        }
      }
      return -1
    },
    /**
     * * 新增组件列表
     * @param chartConfig 新图表实例
     * @param isHead 是否头部插入
     * @param isHistory 是否进行记录
     * @returns
     */
    addComponentList(chartConfig: CreateComponentType | CreateComponentGroupType, isHead = false, isHistory = false): void {
      if (isHistory) {
        chartHistoryStore.createAddHistory(chartConfig)
      }
      if (isHead) {
        this.componentList.unshift(chartConfig)
        return
      }
      this.componentList.push(chartConfig)
    },
    // * 删除单个组件
    removeComponentList(isHistory = true): void {
      try {
        loadingStart()
        const index  = this.fetchTargetIndex()
        if (index !== -1) {
          isHistory ? chartHistoryStore.createDeleteHistory(this.getComponentList[index]) : undefined
          this.componentList.splice(index, 1)
          loadingFinish()
          return
        }
      } catch(value) {
        loadingError()
      }
    },
    // * 更新组件列表某一项的值
    updateComponentList(index: number, newData: CreateComponentType | CreateComponentGroupType) {
      if (index < 1 && index > this.getComponentList.length) return
      this.componentList[index] = newData
    },
    // * 设置页面样式属性
    setPageStyle<T extends keyof CSSStyleDeclaration>(
      key: T,
      value: any
    ): void {
      const dom = this.getEditCanvas.editContentDom
      if (dom) {
        dom.style[key] = value
      }
    },
    // * 移动组件列表层级位置到两端
    setBothEnds(isEnd = false, isHistory = true): void {
      try {
        loadingStart()
        const length = this.getComponentList.length
        if (length < 2) {
          loadingFinish()
          return
        }

        const index  = this.fetchTargetIndex()
        const targetData = this.getComponentList[index]
        if (index !== -1) {
          // 置底排除最底层, 置顶排除最顶层
          if ((isEnd && index === 0) || (!isEnd && index === length - 1 )) {
            loadingFinish()
            return
          }

          // 记录原有位置
          const setIndex = (t:CreateComponentType | CreateComponentGroupType, i:number) => {
            const temp = cloneDeep(t)
            temp.attr.zIndex = i
            return temp
          }

          // 历史记录
          if (isHistory) {
            chartHistoryStore.createLayerHistory(
              setIndex(targetData, index),
              isEnd ? HistoryActionTypeEnum.BOTTOM : HistoryActionTypeEnum.TOP
            )
          }

          // 插入两端
          this.addComponentList(targetData, isEnd)
          this.getComponentList.splice(isEnd ? index + 1: index, 1)
          loadingFinish()
          return
        }
      } catch(value) {
        loadingError()
      }
    },
    // * 置顶
    setTop(isHistory = true): void {
      this.setBothEnds(false, isHistory)
    },
    // * 置底
    setBottom(isHistory = true): void {
      this.setBothEnds(true, isHistory)
    },
    // * 上移/下移互换图表位置
    wrap(isDown = false, isHistory = true) {
      try {
        loadingStart()
        const length = this.getComponentList.length
        if (length < 2) {
          loadingFinish()
          return
        }

        const index:number  = this.fetchTargetIndex()
        if (index !== -1) {
          // 下移排除最底层, 上移排除最顶层
          if ((isDown && index === 0) || (!isDown && index === length - 1)) {
            loadingFinish()
            return
          }
          // 互换位置
          const swapIndex = isDown ? index - 1 : index + 1
          const targetItem = this.getComponentList[index]
          const swapItem = this.getComponentList[swapIndex]

          // 历史记录
          if (isHistory) {
            chartHistoryStore.createLayerHistory(
              targetItem,
              isDown ? HistoryActionTypeEnum.DOWN : HistoryActionTypeEnum.UP
            )
          }
          this.updateComponentList(index, swapItem)
          this.updateComponentList(swapIndex, targetItem)
          loadingFinish()
          return
        }
      } catch(value) {
        loadingError()
      }
    },
    // * 图层上移
    setUp(isHistory = true) {
      this.wrap(false, isHistory)
    },
    // * 图层下移
    setDown(isHistory = true) {
      this.wrap(true, isHistory)
    },
    // * 复制
    setCopy(isCut = false) {
      try {
        loadingStart()
        const index:number  = this.fetchTargetIndex()
        if (index !== -1) {
          const copyData:RecordChartType = {
           charts :this.getComponentList[index],
           type: isCut ? HistoryActionTypeEnum.CUT : HistoryActionTypeEnum.COPY
          }
          this.setRecordChart(copyData)
          window['$message'].success(isCut ? '剪切图表成功' : '复制图表成功!')
          loadingFinish()
        }
      } catch(value) {
        loadingError()
      }
    },
    // * 剪切
    setCut() {
      this.setCopy(true)
    },
    // * 粘贴
    setParse() {
      try {
        loadingStart()
        const recordCharts = this.getRecordChart
        if (recordCharts === undefined) {
          loadingFinish()
          return
        }
        const parseHandle = (e: CreateComponentType | CreateComponentGroupType) => {
          e = cloneDeep(e)
          // 生成新 id
          e.id = getUUID()
          e.attr.x = this.getMousePosition.x + 30
          e.attr.y = this.getMousePosition.y + 30
          return e
        }
        const isCut = recordCharts.type === HistoryActionTypeEnum.CUT
        // 多项
        if (Array.isArray(recordCharts.charts)) {
          recordCharts.charts.forEach((e: CreateComponentType) => {
            this.addComponentList(parseHandle(e), undefined, true)
            // 剪切需删除原数据
            if (isCut) {
              this.setTargetSelectChart(e.id)
              this.removeComponentList(true)
            }
          })
          if (isCut) this.setRecordChart(undefined)
          loadingFinish()
          return
        }
        // 单项
        this.addComponentList(parseHandle(recordCharts.charts), undefined, true)
        if (isCut) {
          this.setTargetSelectChart(recordCharts.charts.id)
          this.removeComponentList()
          this.setRecordChart(undefined)
        }
        loadingFinish()
      } catch(value) {
        loadingError()
      }
    },
    // * 撤回/前进 目标处理
    setBackAndSetForwardHandle(item: HistoryItemType, isForward = false) {
      // 处理画布
      if (item.targetType === HistoryTargetTypeEnum.CANVAS) {
        this.editCanvas = item.historyData as EditCanvasType
        return
      }

      const historyData = item.historyData as CreateComponentType

      // 处理新增类型
      const isAdd = item.actionType === HistoryActionTypeEnum.ADD
      const isDel = item.actionType === HistoryActionTypeEnum.DELETE
      this.setTargetSelectChart(historyData.id)
      if (isAdd || isDel) {
        if ((isAdd && isForward) || (isDel && !isForward)) {
          this.addComponentList(historyData)
          return  
        }
        this.removeComponentList(false)
        return
      }

      // 处理层级
      const isTop = item.actionType === HistoryActionTypeEnum.TOP
      const isBottom = item.actionType === HistoryActionTypeEnum.BOTTOM
      if (isTop || isBottom) {
        if (!isForward) {
          // 插入到原有位置
          if (isTop) this.getComponentList.pop()
          if (isBottom) this.getComponentList.shift()
          this.getComponentList.splice(historyData.attr.zIndex, 0, historyData)
          return
        }
        if (isTop) this.setTop(false)
        if (isBottom) this.setBottom(false)
      }

      const isUp = item.actionType === HistoryActionTypeEnum.UP
      const isDown = item.actionType === HistoryActionTypeEnum.DOWN
      if (isUp || isDown) {
        if ((isUp && isForward) || (isDown && !isForward)) {
          this.setUp(false)
          return
        }
        this.setDown(false)
        return
      }

      // 处理内容修改
      this.getComponentList[this.fetchTargetIndex()] = item.historyData as CreateComponentType
    },
    // * 撤回
    setBack() {
      try {
        loadingStart()
        const targetData = chartHistoryStore.backAction()
        if (!targetData) {
          loadingFinish()
          return
        }
        if (Array.isArray(targetData)) {
          targetData.forEach((e: HistoryItemType) => {
            this.setBackAndSetForwardHandle(e)
          })
          loadingFinish()
          return
        }
        this.setBackAndSetForwardHandle(targetData)
        loadingFinish()

      } catch(value) {
        loadingError()
      }
    },
    // * 前进
    setForward() {
      try {
        loadingStart()
        const targetData = chartHistoryStore.forwardAction()
        if (!targetData) {
          loadingFinish()
          return
        }
        if (Array.isArray(targetData)) {
          targetData.forEach((e: HistoryItemType) => {
            this.setBackAndSetForwardHandle(e, true)
          })
          loadingFinish()
          return
        }
        this.setBackAndSetForwardHandle(targetData, true)
        loadingFinish()

      } catch(value) {
        loadingError()
      }
    },
    // * 移动位置
    setMove(keyboardValue: MenuEnum) {
      const index  = this.fetchTargetIndex()
      if(index === -1) return
      const attr = this.getComponentList[index].attr
      const distance = settingStore.getChartMoveDistance
      switch (keyboardValue) {
        case MenuEnum.ARROW_UP:
          attr.y -= distance
          break;
        case MenuEnum.ARROW_RIGHT:
          attr.x += distance
          break;
        case MenuEnum.ARROW_DOWN:
          attr.y += distance
          break;
        case MenuEnum.ARROW_LEFT:
          attr.x -= distance
          break;
      }
    }, 
    // * 创建分组
    setGroup() {
      try {
        loadingStart()
        const groupClass = new PublicGroupConfigClass()
        this.getTargetChart.selectId.forEach((id: string) => {
          // 获取目标数据并从 list 中移除 (成组后不可再次成组, 断言处理)
          const item = this.componentList.splice(this.fetchTargetIndex(id), 1)[0] as CreateComponentType
          groupClass.groupList.push(item)
        })
        this.addComponentList(groupClass)
        loadingFinish()
      } catch (error) {
        window['$message'].error('创建分组失败,请联系管理员!')
        loadingFinish()
      }
    },
    // * 解除分组
    setUnGroup() {
      try {
        loadingStart()
        const selectGroupIdArr = this.getTargetChart.selectId
        // 解组
        const unGroup = (targetIndex: number) => {
          const targetGroup = this.getComponentList[targetIndex] as CreateComponentGroupType
          targetGroup.groupList.forEach(item => {
            this.addComponentList(item)
          })
          this.setTargetSelectChart(targetGroup.id)
          // 删除分组
          this.removeComponentList(false)
        }

        const targetIndex = this.fetchTargetGroupIndex(selectGroupIdArr[0])
        // 判断目标是否为分组父级
        if(targetIndex !== -1) {
          unGroup(targetIndex)
        } else {
          window['$message'].error('解除分组失败,请联系管理员!')
        }
        loadingFinish()
      } catch (error) {
        window['$message'].error('解除分组失败,请联系管理员!')
        loadingFinish()
      }
    },
    // ----------------
    // * 设置页面大小
    setPageSize(scale: number): void {
      this.setPageStyle('height', `${this.editCanvasConfig.height * scale}px`)
      this.setPageStyle('width', `${this.editCanvasConfig.width * scale}px`)
    },
    // * 计算缩放
    computedScale() {
      if (this.getEditCanvas.editLayoutDom) {
        // 现有展示区域
        const width =
          this.getEditCanvas.editLayoutDom.clientWidth - this.getEditCanvas.offset * 2 - 5
        const height =
          this.getEditCanvas.editLayoutDom.clientHeight - this.getEditCanvas.offset * 4

        // 用户设定大小
        const editCanvasWidth = this.editCanvasConfig.width
        const editCanvasHeight = this.editCanvasConfig.height

        // 需保持的比例
        const baseProportion = parseFloat(
          (editCanvasWidth / editCanvasHeight).toFixed(5)
        )
        const currentRate = parseFloat((width / height).toFixed(5))

        if (currentRate > baseProportion) {
          // 表示更宽
          const scaleWidth = parseFloat(
            ((height * baseProportion) / editCanvasWidth).toFixed(5)
          )
          this.setScale( scaleWidth > 1 ? 1 : scaleWidth)
        } else {
          // 表示更高
          const scaleHeight = parseFloat(
            (width / baseProportion / editCanvasHeight).toFixed(5)
          )
          this.setScale(scaleHeight > 1 ? 1 : scaleHeight)
        }
      } else {
        window['$message'].warning('请先创建画布,再进行缩放')
      }
    },
    // * 监听缩放
    listenerScale(): Function {
      const resize = debounce(this.computedScale, 200)
      // 默认执行一次
      resize()
      // 开始监听
      window.addEventListener('resize', resize)
      // 销毁函数
      const remove = () => {
        window.removeEventListener('resize', resize)
      }
      return remove
    },
    /**
     * * 设置缩放
     * @param scale 0~1 number 缩放比例;
     * @param force boolean 强制缩放
     */
    setScale(scale: number, force = false): void {
      if (!this.getEditCanvas.lockScale || force) {
        this.setPageSize(scale)
        this.getEditCanvas.userScale = scale
        this.getEditCanvas.scale = scale
      }
    }
  }
})