<script lang="ts" setup>
import { ref, onMounted, computed } from 'vue'
import { nextTick } from 'vue'
import BoardView from '@/components/borderView/BoardView.vue'
import {
  Select, SelectOption, Pagination, TreeSelect, Form, FormItem,
  Input, Button, Table, Modal, Textarea, Tooltip, Switch,
  InputNumber, Checkbox
} from 'ant-design-vue'

import { Knife, SysConfig } from '@/imes/biz/SysConfig'
import { ParserMain } from '@/imes/processParser/parseMain'
import { PlusOutlined } from '@ant-design/icons-vue'
import { getListAllSimple, getOrderSource } from '@/api/production/productManagerList'
import { BoardShowType } from '@/imes/vo/enums/BoardShowType'

import { BlockBorderPoint } from '@/imes/vo/point/BlockBorderPoint'
import { BoardEditor } from '@/imes/biz/RenderNewBoard'
import { BasicTable, TableAction, useTable } from '@/components/Table'
import { optimizeColumns1 } from '../production/productManagerList/productManagerList.data'
import { DataHandleServe } from '@/imes/dataHandle/DataHandleServe'
import { convertData } from '@/imes/common/transform'
import { blockborderClass } from '@/imes/dataClass/blockborderClass'
import { Arc2d, Curve2d } from '@/imes/common/base/CAD'
import { ProcessorContext } from './dataHandle/base'
import { OptimizeLayoutProcessor } from './dataHandle/optimizeLayout/optimizeLayout'
import { ToolsHelper } from './dataHandle/tools/tool'
import {
  BlockPlaceResult, BoardPlaceResult, BoardPosition, MaterialPlaceResult, PlaceBoard, PlaceStyle,
  PlaceBlock, PlaceBlockDetail,
  PlaceMaterial, RemainBlock,
  PlacePositionClass,
  CodeParams,
  BlockHole,
  BlockModel,
  BlockModelPoint
} from './dataHandle/confClass'
import { BlockSizePlus } from './dataHandle/common/LayoutEngine/BlockSizePlus'
import { Point } from './dataHandle/common/Vector2'
import { PlacePositionHelper } from './dataHandle/common/PlacePostionHelper'
import { DisPoseModelInBoardBorder } from './dataHandle/common/LayoutEngine/DisposeModelInBoardBorder'
import { getMaterialSealEdge } from './dataHandle/common/BlockSealEdge'
import { ArrayExt } from './dataHandle/ArrayExt'
import { CutOrder } from './dataHandle/common/cutorder/CutOrder'
import { CutPointHelper } from './dataHandle/common/cutorder/CutPointHelper'
import { CodeParamsList, CodeParamsObj } from '@/imes/processParser/confClass'
import { BlockHelper } from './dataHandle/common/LayoutEngine/BlockHelper'


const selectedMachineID = ref() // 机台选中
const machineList = ref<any>([]) // 机台列表
// 1920321997498220544 1907276351086264320 1920401449485860864 1920739893772812288
const orderNo = ref('1920401449485860864')
const canvasWidth = ref(1200)
const canvasHeight = ref(650)
const paginationCurrent = ref<any>(1)
const paginationCurrentAll = ref<any>(1) 
const boardEditor = ref<BoardEditor>()
const canvasMain = ref()
const canvas = ref()
const isOptimizeing = ref(false)
const _handleServe = ref<OptimizeLayoutProcessor | null>(null)
const selectVal = ref<any>()
const plateSelectOptions = ref<any>([])
const parserMain = ref<ParserMain>(new ParserMain())
const testData1 = ref('') 
const dataBase = ref<any>(null)



// 添加显示标志位数组，用于记录当前需要绘制的内容
const displayFlags = ref({
  isLockd: false,  // 是否锁定
  showBlocks: false,  // 是否显示小板
  showCutPoints: false,  // 是否显示下刀点
  showCutOrders: false,   // 是否显示开料顺序
  showCutNo: false,   // 是否显示板号
  showCutArrow: false,  // 是否显示开料方向箭头
  showManualPlace: false,  // 是否显示手动排版
  showHoles: false,  // 是否显示孔洞
  showModels: false,  // 是否显示造型
});

// 初始化解析器
parserMain.value.setDeviceByKey('device1')

// 画布控制器
const canvasController = ref({
  showType: BoardShowType.NORMAL,
  showHelpCut: false,
  isDragingBlock: false,
  clickedBlock: new PlaceBlock(),
  clickedScrapBlock: new RemainBlock(1, 1, 100, 100),
  dragedDistance: Point,
  beginDragPosition: Point,
  mousePostion: Point,
  dragingBlockPoint: BlockBorderPoint,
  closestBlockPoint: BlockBorderPoint
})

const currentMaterial = computed(() => {
  if (!dataBase.value?.materialList) return null;
  const mIndex = dataBase.value.materialList.findIndex(e => e.goodsId === selectVal.value);
  return mIndex >= 0 ? dataBase.value.materialList[mIndex] : null;
});

const currentBoard = computed(() => {
  if (!currentMaterial.value?.boardList) return null;
  const pIndex = paginationCurrent.value - 1;
  return pIndex >= 0 && pIndex < currentMaterial.value.boardList.length
    ? currentMaterial.value.boardList[pIndex]
    : null;
});

onMounted(() => {
  getOptions();
})

const [registerTable, { setTableData, updateTableData, getDataSource }] = useTable({
  title: '',
  columns: optimizeColumns1,
  useSearchForm: false,
  rowKey: 'id',
  pagination: false,
  canResize: true,
  maxHeight: 100,
  showTableSetting: false,
  actionColumn: {}
})

/**
 * 获取弹出容器
 */
function getPopupContainer(node?: HTMLElement): HTMLElement {
  return (node?.parentNode as HTMLElement) ?? document.body
}

/**
 * 获取机台列表
 */
async function getOptions() {
  const res = await getListAllSimple({ type: 1 });
  if (res) {
    machineList.value = res;
    selectedMachineID.value = res[0].id;
    _getPlaceOrderData();
  }
}

/**
 * 订单变化处理
 */
function orderNoChange() {
  _getPlaceOrderData();
}

/**
 * 机台变化处理
 */
function machineChange() {
  // 机台变化逻辑
}

/**
 * 获取排版订单数据
 */
async function _getPlaceOrderData() {
  const params = {
    // orderId: '1792854086534561792',
    // machineId: '14193',
    orderId: orderNo.value,
    machineId: selectedMachineID.value,
  };

  const res = await getOrderSource(params);
  if (!res) return;

  let conf = JSON.parse(res.machineDTO.setting);
  let tempData = { ...res, optimizeBoardModelDOS: [] };
  let newGoodsList: any[] = [];
  for (let material of tempData.goodsList) {
    if (material.height == 0) material.height = 2440;
    if (material.width == 0) material.width = 1220;

    if (newGoodsList.findIndex(e => e.goodsId == material.goodsId) == -1) {
      newGoodsList.push(material);
    }
  }

  tempData.goodsList = newGoodsList;

  let newTestData = convertData(tempData);
  let goodsId = newTestData.materialList.map(e => e.goodsId)[0]

  newTestData.blockList.forEach(block => {
    block.goodsId = goodsId
  });
  dataBase.value = newTestData;

  let sysConfig = new SysConfig(conf);
  let _sysConfig = { ...sysConfig };

  setTableData(newTestData.materialList);
  selectVal.value = newTestData.materialList[0].goodsId;
  plateSelectOptions.value = newTestData.materialList;
  _sysConfig.boardBorder = _sysConfig.cutBoardBorder;

  let eleCanvasMain = document.getElementsByClassName('contentMain')[0];
  const { clientWidth, clientHeight } = eleCanvasMain;
  canvasWidth.value = clientWidth - 10;
  canvasHeight.value = clientHeight - 30;

  await nextTick();
  boardEditor.value = new BoardEditor(
    canvas.value.canvasRef,
    _sysConfig,
    canvasController.value
  );

  boardEditor.value.boardWidth = sysConfig.boardWidth;
  boardEditor.value.boardLength = sysConfig.boardLength;
  boardEditor.value.drawBase();
  boardEditor.value.setSysConfig(_sysConfig);
}

 
async function initHandleServe1() {

  let newTestData = dataBase.value;
  //#region 刀库
  let toolsHelperClass = new ToolsHelper();
  let contextKnife: ProcessorContext<Knife[], any, any> = {
    input: newTestData.sysConfig.knifeList,
    output: {},
    params: newTestData.sysConfig
  }
  const toolsHelper = toolsHelperClass.exec(contextKnife)
  //#endregion

  //#region 优化排版
  let input = {
    materialList: newTestData.materialList,
    blockList: newTestData.blockList,
    blockDetailList: newTestData.blockDetailList,
    toolsHelper: toolsHelper,
  }
  let params = newTestData.sysConfig

  let context: ProcessorContext<any, Function, any> = {
    input: input,
    params: params,
    output: optimizeLayoutProcessorCallBack
  };
  const optimizeLayoutProcessor = new OptimizeLayoutProcessor()
  let res = optimizeLayoutProcessor.exec(context)

  _handleServe.value = optimizeLayoutProcessor
  //#endregion
}


/** 优化的处理器回调--这部分  不做到处理器 */
async function optimizeLayoutProcessorCallBack(context) {
  console.log('optimizeLayoutProcessorCallBack', context);
  const { data, info } = context;

  if (['noBan', 'stop'].includes(info.type)) {
    await _handleServe.value?.terminateWorker({ goodsId: context.data.pm.goodsId });

    return;
  }

  // 优化算法拿到优化数据后 各部门根据情况 将数据加载到各自的数据结构中
  let materialPlaceResult = await getMaterialPlaceResult(data);
  if (materialPlaceResult) {
    const { placeResult, pm } = materialPlaceResult;
    const remain = placeResult.boards.filter(e => e.isRemainBoard == true);

    for (const i in dataBase.value.materialList) {
      let material = dataBase.value.materialList[i];

      if (material.goodsId == pm.goodsId) {
        // let hasResPm = _handleServe.value?.handlePlaceResult(placeResult, pm);
        let _hasResPm = await handleTempPlaceResultToPlaceMaterial(placeResult, pm);

        dataBase.value.materialList[i] = {
          ...material,
          ...pm,
          ..._hasResPm,
          optimizingAvgUsageRateExcludeLastBoard: placeResult.avgUsageRateExcludeLastBoard.toFixed(3),
          optimizingUsageRateLastBoard: placeResult.usageRateLastBoard.toFixed(3),
          optimizingBoardCount: placeResult.boardCount,
          optimizingRemainBoardCount: remain.length,
          selectedBlockCount: pm.blockList.length,
        };
      }
    }

    setTableData(dataBase.value.materialList);
  }
}

/** 数据处理 将优化数据转 为 MaterialPlaceResult */
function getMaterialPlaceResult(data) {
  let {
    bList, best, yl, pm, width, length
  } = data
  const config = dataBase.value.sysConfig

  let blocks = bList
  let retData = new MaterialPlaceResult()
  let boardCount = 0
  let remainCount = 0
  let border = config.cutBoardBorder
  let borderOff = (pm.diameter + pm.cutKnifeGap) / 2


  // 所有大板上的小板面积
  let size_all = 0

  for (let i = 0; i < best.length; i++) {
    let bd = best[i]
    let isRemainBoard = false
    boardCount = retData.boards.length + 1
    if (i < yl.length) // 余料板
    {
      width = yl[i].w + border * 2 - borderOff * 2
      length = yl[i].l + border * 2 - borderOff * 2
      isRemainBoard = true
      remainCount++
    }

    let boardResult = new BoardPlaceResult()
    boardResult.boardId = boardCount
    boardResult.width = width
    boardResult.length = length
    boardResult.isRemainBoard = isRemainBoard

    let pid = 0
    for (let b of bd) {
      pid++
      let block = blocks[b.bangid]
      let placeStyle = PlaceStyle.FRONT
      if (!block) {
        return
      }
      let faceF = block.isTurnFaceToPlace || false
      let isTurnFaceToPlace = config.placeOriginByBoardLocation && (
        config.boardLocation == BoardPosition.RIGHT_BOTTOM || config.boardLocation == BoardPosition.LEFT_TOP)
      if (isTurnFaceToPlace)
        faceF = !faceF
      if (faceF) // 翻面开料
      {
        if (block.texture == 0) {
          placeStyle = PlaceStyle.BACK
        }
        else if (block.texture == 2) {
          placeStyle = PlaceStyle.BACK_TURN_LEFT
        }
        else {
          placeStyle = (b.pbg == block.placeFullLength ? PlaceStyle.BACK : PlaceStyle.BACK_TURN_LEFT)
        }
      }
      else {
        if (block.texture == 0) {
          placeStyle = PlaceStyle.FRONT
        }
        else if (block.texture == 2) {
          placeStyle = PlaceStyle.FRONT_TURN_RIGHT
        }
        else {
          placeStyle = (b.pbg == block.placeFullLength ? PlaceStyle.FRONT : PlaceStyle.FRONT_TURN_RIGHT)
        }
      }

      let br: any = null
      br = new BlockPlaceResult(block.blockNo, boardCount, pid, b.x, b.y, b.pbk, b.pbg, placeStyle, block.area)
      boardResult.blocks.push(br)
      boardResult.area += block.area
    }
    retData.boards.push(boardResult)
    size_all += boardResult.area

    let val = (size_all - boardResult.area) / (retData.boards.length - 1)
    retData.avgUsageRateAll = size_all / retData.boards.length
    retData.avgUsageRateExcludeLastBoard = Number.isNaN(val) ? boardResult.area : val
    retData.usageRateLastBoard = boardResult.area
    retData.boardCount = retData.boards.length
  }
  retData.boardCount = retData.boards.length // 大板数
  let remainBoardCount = retData.boards.filter(t => t.remainNo != '').length // 异形大板数
  let remianCount = 0

  if (Array.isArray(pm.remainBoardList)) {
    pm.remainBoardList.forEach(e => {
      if (e?.placeBoardJSON) {
        let str = e?.placeBoardJSON
        e.placeBoardList = JSON.parse(str)
        remianCount += e.placeBoardList.length
      }
    })
  }

  retData.remainBoardCount = pm?.remainBoardList ? remianCount : yl.length + remainBoardCount




  return { placeResult: retData, pm }
}

async function handleTempPlaceResultToPlaceMaterial(_placeResult: MaterialPlaceResult, _pm: PlaceMaterial) {
  console.log('确认优化生效 affirmPlace')
  let pm: PlaceMaterial = _pm
  pm.tempBestPlaceResult = _placeResult
  const config = dataBase.value.sysConfig
  // 没发现优化结果
  if (!pm.tempBestPlaceResult)
    return

  let placeResult = pm.tempBestPlaceResult

  let orgBoardList = pm.boardList

  let dic: any = [] // 存放当前 优化的小板

  pm.boardList = []
  let boardId1 = 1
  // 第一次   false
  if (pm.tempPlaceResultOnyUnlockedBoard) {
    for (let pb of orgBoardList) {
      if (pb.isLocked == false && pb.cutedType == 0) // 未锁定
      {
        pb.blockList.forEach(i => dic[i.blockNo] = i)
      }
      else // 锁定
      {
        if (pb.isAdnormal()) {
          let sb = pm.remainBoardList.find(t => t.id == Number(pb.boardNo))
          if (sb)
            sb.isUsed = true
        }
        pb.boardId = boardId1
        pm.boardList.push(pb)
        boardId1++
      }
    }
  }
  else {
    pm.blockList.forEach(i => dic[i.blockNo] = i)
  }

  // 0904 修复 需求改造后 导致 这里的dic 最终为空
  if (Object.keys(dic).length == 0) {
    pm.blockList.forEach(i => dic[i.blockNo] = i)
  }

  let locator = config.boardLocation
  // 大板优化结果
  let boardId = 0
  for (let bpr of placeResult.boards) {
    boardId++
    // bpr.isRemainBoard  false
    let bW = bpr.isRemainBoard ? bpr.width : pm.width
    let bL = bpr.isRemainBoard ? bpr.length : pm.length
    let pb = new PlaceBoard(boardId, bW, bL, bpr.remainId, bpr.remainNo)
    pb.isCreateRemainSpace = true

    for (let bInfo of bpr.blocks) {
      let block: PlaceBlock = dic[bInfo.blockId]

      if (block) {
        block.isPlaced = true
        block.boardId = boardId
        block.placeId = bInfo.placeId
        block.placeX = bInfo.placeX
        block.placeY = bInfo.placeY
        // console.log('重置 开料面 开料信息 after', block.boardId, block.blockNo, block, block.placeStyle, bInfo.placeStyle)

        /**
         * 雕刻机(钻孔、拉槽、开料)优化排版，开料排版面(开料正面)选择顺序：排版面>>造型>>排钻>>设计正面
            1. 排版面
            小板设计排版面为正面或反面，设置对应面为开料排版面，
            小板设计排版面为随意面，则继续；
            2. 造型
            小板只有单面造型，设置对应面为开料排版面，
            小板双面无造型或双面有造型，则继续；
            3. 排钻
            小板有大孔(偏心轮锁孔)，设置对应面为开料排版面，
            小板无大孔(偏心轮锁孔)，则设置孔多的面为开料排版面，
            小板无孔，则继续；
            4. 设计正面
            默认设置设计正面为开料排版面。
         */

        block.placeStyle = bInfo.placeStyle

        let posOff = BlockSizePlus.getOffDis(block)// this.getOffDis(block)

        block.placeOffX = posOff.x
        block.placeOffY = posOff.y
        block.placeX = bInfo.placeX + posOff.x
        block.placeY = bInfo.placeY + posOff.y

        if (bInfo.placeStyle == PlaceStyle.FRONT || bInfo.placeStyle == PlaceStyle.FRONT_TURN_BACK
          || bInfo.placeStyle == PlaceStyle.BACK || bInfo.placeStyle == PlaceStyle.BACK_TURN_BACK) {
          block.placeWidth = block.cutWidth
          block.placeLength = block.cutLength
        }
        else {
          block.placeWidth = block.cutLength
          block.placeLength = block.cutWidth
        }

        block.isAutoPlaced = true
        block.isOverlap = false
        block.cutOrder = 0
        pb.blockList.push(block)
        pb.blockCount++
        pb.blockArea += block.area
        delete dic[bInfo.blockId] // 移除block;
      } else {

      }
    }
    if (bpr.isScrap) {
      // 设置前余料板的使用状态,将不需要的释放.
      console.log('设置前余料板的使用状态,将不需要的释放.')
      let sb = pm.remainBoardList.find(t => t.id == bpr.remainId)
      if (sb) {
        sb.isUsed = true

        if (sb.placeStyle % 2 != 0) {
          pb.width = sb.length
          pb.length = sb.width
        }
        let pl = sb.placePolyline
        pb.points = sb?.placePolyline?.LineData.map((t) => { return { x: t.pt.x, y: t.pt.y, bul: t.bul } }) || []
        // pb.StoreNo = sb.StoreHouse;
      }
    }
    pb.usageRate = Math.round(10000 * pb.blockArea / pb.area) / 100
    pm.boardList.push(pb)
    console.log('大板靠板翻转', pb.boardId, locator)

    // 大板靠板翻转

    PlacePositionHelper.turnPlacePosition(pb, locator, config)
    for (let block of pb.blockList) {
      // 重置 开料面 开料信息
      // console.log('重置 开料面 开料信息', block.boardId, block.blockNo, block, block.placeStyle)
      if (block.placeStyle == null || block.placeStyle == undefined) {
        console.log('handleTempPlaceResultToPlaceMaterial error ！block.placeStyle is null or undefined')
      } else {
        PlacePositionClass.resetPlaceStyle(block, block.placeStyle)
      }

    }
  }


  // 大板长边两侧 width 范围内 避免出现造型    DisPoseModelInBoardBorderWidth > 0 生效

  DisPoseModelInBoardBorder(
    pm,
    config.boardBorderModelRange,
    config.boardBorderModelModeToFace,
    config.boardBorderModelByMachine,
    config.modelNearBoardBorder,
  )

  // for (let pb of pm.boardList) {
  //     // 重设大板汇总 重设 大板开料 顺序,下刀点
  //     this.resetPlaceBoard(pm, pb)
  //     // 检查干涉
  //     if (pb.isLocked == false && pb.cutedType == 0)
  //         this.checkOverlapInBoard(pm, pb)
  // }

  let rBoardCount = placeResult.boardCount
  let rUseSize_avg = placeResult.avgUsageRateAll
  let rUseSize_noLast = placeResult.avgUsageRateExcludeLastBoard
  let rUseSize_last = placeResult.usageRateLastBoard

  pm.avgUsageRateAll = rUseSize_avg
  pm.avgUsageRateExcludeLastBoard = rUseSize_noLast
  pm.usageRateLastBoard = rUseSize_last
  pm.boardCount = pm.boardList.length
  pm.remainBoardCount = placeResult.remainBoardCount
  pm.minBoardId = 1
  pm.maxBoardId = pm.boardCount

  pm.edgeSealLengthList = getMaterialSealEdge(pm)

  pm.boardCountFlipFace = ArrayExt.count(pm.boardList, t => t.isTwoFaceProcessing())

  pm.isOptimized = true
  pm.tempBestPlaceResult = null
  pm.tempPlaceResultError = ''

  let mesg = ''
  let c = 0
  for (let v in dic) {
    mesg += `${v} `
    c++
  }

  mesg = `有${c}片小板未能排入大板,有可能是尖角导致优化失败.${mesg}`

  if (c > 0) {
    console.log(pm)
    // createMessage.error(mesg)

    throw new Error(mesg)
  }

  return pm
}

/**
 * 绘制下刀点
 */
function drawCutPoint() {
  if (!boardEditor.value || !dataBase.value || !_handleServe.value) return;

  let mIndex = dataBase.value.materialList.findIndex(e => e.goodsId == selectVal.value);
  let pIndex = paginationCurrent.value - 1;

  if (mIndex >= 0 && dataBase.value.materialList[mIndex].boardList?.length > 0) {
    const pm = dataBase.value.materialList[mIndex];
    const pb = pm.boardList[pIndex];

    // 计算开料顺序和下刀点
    // _handleServe.value.autoCalcCutOrder(pm, pb);
    CutPointHelper.autoFindCutPoint(pm, pb)
    // 设置显示标志位，只显示小板和下刀点
    displayFlags.value.showBlocks = true;
    displayFlags.value.showCutPoints = !displayFlags.value.showCutPoints; // 切换下刀点显示状态

    // 重新绘制
    // reDrawCanvas();
  } else {
    alert('请先进行优化！');
  }
}
 
/**
 * 绘制开料顺序
 */
function drawSortingPlace() {
  if (!boardEditor.value || !dataBase.value || !_handleServe.value) return;

  let mIndex = dataBase.value.materialList.findIndex(e => e.goodsId == selectVal.value);
  let pIndex = paginationCurrent.value - 1;

  if (mIndex >= 0 && dataBase.value.materialList[mIndex].boardList?.length > 0) {
    const pm = dataBase.value.materialList[mIndex];
    const pb = pm.boardList[pIndex];
    const config = dataBase.value.sysConfig
    // 计算所有板材的 开料顺序
    let newList = CutOrder.autoSetCutOrder(dataBase.value.materialList, config)
    // 计算当前板材的开料顺序
    // CutOrder.autoCalcCutOrder(pm,pb,false,config)
    // 设置显示标志位，只显示小板和开料顺序
    displayFlags.value.showBlocks = true;
    displayFlags.value.showCutOrders = !displayFlags.value.showCutOrders; // 切换开料顺序显示状态

    // 重新绘制
    // reDrawCanvas();
  } else {
    alert('请先进行优化！');
  }
}

 

/**
 * 处理画布事件
 */
function boardViewEvent(name, e) {
  if (!boardEditor.value) return;

  if (name === 'CanvasEvent_MouseDown') {
    // 处理鼠标按下事件
    boardEditor.value.CanvasEvent_MouseDown(e);
  } else if (name === 'CanvasEvent_MouseMove') {
    // 使用节流函数处理鼠标移动事件，减少事件触发频率
    throttledMouseMove(e);
  } else if (name === 'CanvasEvent_Mouseup') {
    boardEditor.value.CanvasEvent_Mouseup(e);
  } else if (name === 'CanvasEvent_dblclick') {
    // 双击事件处理
  } else if (name === 'CanvasEvent_Wheel') {
    // 滚轮事件处理
  } else if (name === 'keyDown') {
    boardEditor.value.keyDown(e);
  }
}

const throttledMouseMove = throttle((e) => {
  if (boardEditor.value) {
    boardEditor.value.CanvasEvent_MouseMove(e);
  }
}, 16);

/**
 * 节流函数
 */
function throttle(fn, delay) {
  let lastCall = 0;
  return function (...args) {
    const now = Date.now();
    if (now - lastCall >= delay) {
      lastCall = now;
      fn.apply(this, args);
    }
  };
}


/**
 * 开始排版
 */
function startPlace() {
  // initHandleServe();
  initHandleServe1();

  // 设置显示标志位，显示所有内容
  displayFlags.value.showBlocks = true;
  displayFlags.value.showCutPoints = true;
  displayFlags.value.showCutOrders = true;
  displayFlags.value.showCutArrow = true;
  displayFlags.value.showCutNo = true;
  displayFlags.value.showHoles = true;
  displayFlags.value.showModels = true;
}

 
/**
 * 清空画布
 */
function clearCanvas() {
  // 重置显示标志位
  displayFlags.value.showBlocks = false;
  displayFlags.value.showCutPoints = false;
  displayFlags.value.showCutOrders = false;
  displayFlags.value.showCutArrow = false;
  displayFlags.value.showCutNo = false;
  displayFlags.value.showHoles = false;
  displayFlags.value.showModels = false;
  // 清空画布
  boardEditor.value?.clearCanvas();
}
   

/**
 * 获取解析器参数
 */
function getParserParams() {
  handleTemplateData();
}

 
/**
 * 处理模板数据
 */
async function handleTemplateData() {
  // 获取模板和范例
  let templateData = parserMain.value._device.getTemplateData();
  console.log(templateData, dataBase.value);

  if (!currentMaterial.value || !currentBoard.value) {
    alert('请先进行优化！');
    return;
  }

  // 准备代码参数列表
  let data: CodeParamsList = {
    processList: [],
  };

  // 获取速度参数
  let freeSpeed = _handleServe.value?.freeSpeed || 10000;
  let workSpeed = _handleServe.value?.workSpeed || 8000;
  let modelSpeed = _handleServe.value?.modelSpeed || 8000;
  let holeSpeed = _handleServe.value?.holeSpeed || 8000;
  
  /** 根据哪个加工面加工 */
  let doBackFace = true
  for (const template of templateData) {
    // 必须要有指令和代码
    if (!template.value || !template.orderStr) continue;

    if (template.isLoop) {
      // 处理循环节点（加工刀路数据）
      let material = currentMaterial.value;
      let board = currentBoard.value;
      // 根据开料顺序做个排序
      board.blockList = board.blockList.sort((a, b) => a.cutOrder - b.cutOrder)

      //#region 排钻

      /**
       * 先对该大板内所有小板上的孔进行分析
      */

      let allHoles: BlockHole[] = await BlockHelper.GetHoles_BoardAllBlocksByDoFace(board,doBackFace)
      // 对孔列表 根据 孔直径 排序
      allHoles = allHoles.sort((a, b) => a.radius - b.radius)

      for (const key in allHoles) {
        let hole = allHoles[key]
        let block: PlaceBlock = board.blockList.find(e => e.blockNo == hole.blockNo)

        // 加工项 孔的
        let temp: CodeParamsObj = {
          processItemInfo: {
            code: template.value,
            order: template.orderStr,
            block: {
              blockNo: block.blockNo,
              cutLength: block.cutLength,
              cutWidth: block.cutWidth
            },
            knife: {
              diameter: hole.radius * 2
            },
          }
        };
        let list: CodeParams[] = [];
        let depth = hole.depth >= block.thickness ? block.thickness : hole.depth
        // 刀移动到孔的安全点
        let moveToHolePoint = pointToCodeParams(hole.pointX, hole.pointY, block.placeX, block.placeY)
        moveToHolePoint.dir = 0
        moveToHolePoint.z = 30
        moveToHolePoint.f = freeSpeed
        list.push(moveToHolePoint)
        // 刀下到版面
        let moveToblockToDoHole = pointToCodeParams(hole.pointX, hole.pointY, block.placeX, block.placeY)
        moveToblockToDoHole.dir = 0
        moveToblockToDoHole.z = -block.thickness
        moveToblockToDoHole.f = freeSpeed
        list.push(moveToblockToDoHole)
        // 下刀
        let knifeDown_DoHole = pointToCodeParams(hole.pointX, hole.pointY, block.placeX, block.placeY)
        knifeDown_DoHole.z = -depth
        knifeDown_DoHole.dir = 1
        knifeDown_DoHole.f = holeSpeed
        list.push(knifeDown_DoHole)
        // 抬刀
        let knifeEnd_DoHoleEnd = pointToCodeParams(hole.pointX, hole.pointY, block.placeX, block.placeY)
        knifeEnd_DoHoleEnd.dir = 0
        knifeEnd_DoHoleEnd.z = 30
        knifeEnd_DoHoleEnd.f = freeSpeed
        list.push(knifeEnd_DoHoleEnd)

        temp.list = list

        data.processList?.push(temp);
      }

      //#endregion

      //#region 造型

      //  所有造型
      let allModels: BlockModel[] = await BlockHelper.GetModels_BoardAllBlocksByDoFace(board,doBackFace)
      allModels = allModels.sort((a, b) => a.knifeRadius - b.knifeRadius)

      for (const key in allModels) {
        let model = allModels[key]
        let block: PlaceBlock = board.blockList.find(e => e.blockNo == model.blockNo)
        let { placeX, placeY } = block;

        let temp: CodeParamsObj = {
          processItemInfo: {
            code: template.value,
            order: template.orderStr,
            block: {
              blockNo: block.blockNo,
              cutLength: block.cutLength,
              cutWidth: block.cutWidth
            },
            knife: {
              diameter: model.realKnifeRadius * 2
            },
          }
        };
        let list: CodeParams[] = [];
        let realPointList:any[] = []
        //  model.realPointList.forEach((p,i)=>{
        //   if(p.curve !=0 || p.radius != 0){

        //   }
        //  })
        for (let index = 0; index < model.realPointList.length; index++) {
          const p = model.realPointList[index];
          let last_p: BlockModelPoint;
          if (index == 0) {
            last_p = model.realPointList[model.realPointList.length - 1]
          } else {
            last_p = model.realPointList[index - 1]
          }
          // p.curve
          // p.radius
          let new_p = { ...p, radius: last_p.radius, curve: last_p.curve }
          realPointList.push(new_p);
        }


        let depth = model.depth >= block.thickness ? block.thickness : model.depth

        // 移动到起点
        let codeLineStart = pointToCodeParams(realPointList[0].pointX, realPointList[0].pointY, placeX, placeY)
        codeLineStart.dir = 0;
        codeLineStart.z = 30;
        codeLineStart.f = freeSpeed;
        list.push(codeLineStart);
        // 下刀至版面
        let knifeToBlock_DoModel = pointToCodeParams(realPointList[0].pointX, realPointList[0].pointY, placeX, placeY)
        knifeToBlock_DoModel.dir = 0;
        knifeToBlock_DoModel.z = block.thickness;
        knifeToBlock_DoModel.f = freeSpeed
        list.push(knifeToBlock_DoModel)
        // 扎入 下刀至起点
        let knifeInnerBlock_DoBlock = pointToCodeParams(realPointList[0].pointX, realPointList[0].pointY, placeX, placeY)
        knifeInnerBlock_DoBlock.dir = 1;
        knifeInnerBlock_DoBlock.z = -depth
        knifeInnerBlock_DoBlock.f = modelSpeed
        list.push(knifeInnerBlock_DoBlock)
        // 开始造型走刀
        for (const modelPoint of realPointList) {
          let codeLineMove = pointToCodeParams(modelPoint.pointX, modelPoint.pointY, placeX, placeY, modelPoint.curve)
          codeLineMove.z = -depth
          codeLineMove.f = modelSpeed
          if (modelPoint.radius != 0) {
            codeLineMove.r = modelPoint.radius
          }
          list.push(codeLineMove)
        }
        // 走刀结束 抬刀
        let endPoint = realPointList[realPointList.length - 1]
        let codeLineEnd = pointToCodeParams(endPoint.pointX, endPoint.pointY, placeX, placeY)
        codeLineEnd.dir = 0
        codeLineEnd.f = freeSpeed
        codeLineEnd.z = 30
        list.push(codeLineEnd)
        temp.list = list
        data.processList?.push(temp);
      }
      //#endregion

      //#region 开料

      // 轮廓的集合 开料用
      let borderFinalList = board.blockList.map(e => e.blockDetail.borderContour.borderFinal);
      for (const i in borderFinalList) {
        let block = board.blockList[i];
        let border = borderFinalList[i];

        // 添加标记
        let temp1: CodeParamsObj = {
          processItemInfo: {
            code: 'MARK',
            order: 'Mark',
            codeParams: block.blockNo + ' cut block'
          }
        };
        data.processList?.push(temp1);

        // 加工项 开料的
        let temp: CodeParamsObj = {
          processItemInfo: {
            code: template.value,
            order: template.orderStr,
            block: {
              cutLength: block.cutLength,
              cutWidth: block.cutWidth
            },
            knife: {
              diameter: material.diameter
            }
          }
        };

        // 加工刀路信息 代码生成参数列表
        let list: CodeParams[] = [];
        let { placeX, placeY } = block;

        // 移动到起点
        let codeLineStart = BoardToCodeParams(border[0], placeX, placeY);
        codeLineStart.dir = 0;
        codeLineStart.z = 30;
        codeLineStart.f = freeSpeed;
        list.push(codeLineStart);

        // 下刀到板面
        let codeLine1 = BoardToCodeParams(border[0], placeX, placeY);
        codeLine1.dir = 0;
        codeLine1.z = block.thickness;
        codeLine1.f = freeSpeed;
        list.push(codeLine1);

        // 扎入
        let codeLine2 = BoardToCodeParams(border[0], placeX, placeY);
        codeLine2.dir = 1;
        codeLine2.z = 0;
        codeLine2.f = workSpeed;

        // 走刀
        for (const p of border) {
          // if (block.blockNo == '25044454400') {
          //   debugger
          // }
          let codeLine = BoardToCodeParams(p, placeX, placeY);
          codeLine.z = -block.thickness;
          codeLine.f = workSpeed;
          list.push(codeLine);
        }

        // 回到起点
        let codeLine3 = BoardToCodeParams(border[0], placeX, placeY);
        codeLine3.z = -block.thickness;
        codeLine3.f = freeSpeed;
        list.push(codeLine3);

        // 抬刀
        let codeLineEnd = BoardToCodeParams(border[0], placeX, placeY);
        codeLineEnd.dir = 0;
        codeLineEnd.z = 30;
        codeLineEnd.f = freeSpeed;
        list.push(codeLineEnd);

        temp.list = list;
        data.processList?.push(temp);
      }
      //#endregion
    } else {
      // 处理非循环节点（文件头尾）
      let temp: CodeParamsObj = {
        processItemInfo: {
          code: template.value,
          order: template.orderStr
        }
      };

      if (template.params) {
        temp.processItemInfo.codeParams = template.params;
      }

      data.processList?.push(temp);
    }
  }

  console.log('处理完成', data);

  // 生成代码
  let str = await parserMain.value.getCode(data);
  testData1.value = str;
  console.log('最终结果', str);

}

/**
 * 将板轮廓转换为代码参数
 * border 轮廓线
 * placeX 板件优化X坐标
 * placeY 板件优化Y坐标
 */
function BoardToCodeParams(border: Curve2d | Arc2d, placeX = 0, placeY = 0): CodeParams {
  let codeLine: CodeParams = {};
  codeLine.x = border.EndPoint.m_X + placeX;
  codeLine.y = border.EndPoint.m_Y + placeY;
  codeLine.dir = 1;

  if (border instanceof Arc2d || (Reflect.has(border, 'm_Radius') && border['m_Radius'] != 0)) {
    codeLine.r = border.m_Radius;
    if (border.Bul > 0) {
      codeLine.dir = 3;
    } else if (border.Bul < 0) {
      codeLine.dir = 2;
    }
  }

  return codeLine;
}
/** 
 * x , y 点坐标
 * hole 孔
 * placeX 板件优化X坐标
 * placeY 板件优化Y坐标
*/

function pointToCodeParams(x, y, placeX = 0, placeY = 0, bul?) {
  let codeLine: CodeParams = {}
  codeLine.x = x + placeX
  codeLine.y = y + placeY

  if (bul != undefined) {
    if (bul > 0) {
      codeLine.dir = 3
    } else if (bul < 0) {
      codeLine.dir = 2
    }
  }
  return codeLine
}
/**
 * 重新绘制画布
 */
function reDrawCanvas() {
  if (!boardEditor.value || !dataBase.value) return;

  let mIndex = dataBase.value.materialList.findIndex(e => e.goodsId == selectVal.value);
  let pIndex = paginationCurrent.value - 1;

  if (mIndex >= 0 && dataBase.value.materialList[mIndex].boardList?.length > 0) {
    const pm = dataBase.value.materialList[mIndex];
    const pb = pm.boardList[pIndex];

    // 确保每个板件都有开料顺序和下刀点
    if (_handleServe.value && pb.blockList.some(block => !block.cutOrder)) {
      _handleServe.value.autoCalcCutOrder(pm, pb);
    }

    boardEditor.value.setMaterial(pm);
    boardEditor.value.setBoard(pb);

    // 清空画布并绘制基础内容
    boardEditor.value.clearCanvas();
    boardEditor.value.drawBase();
    boardEditor.value.drawBoard(pb);

    boardEditor.value.setDisplayFlags({
      isLockd: displayFlags.value.isLockd,
      showBlocks: displayFlags.value.showBlocks,
      showCutPoints: displayFlags.value.showCutPoints,
      showCutOrders: displayFlags.value.showCutOrders,
      showCutArrow: displayFlags.value.showCutArrow,
      showCutNo: displayFlags.value.showCutNo,
      showHoles: displayFlags.value.showHoles,
      showModels: displayFlags.value.showModels,
      showManualPlace: displayFlags.value.showManualPlace
    });

    boardEditor.value.drawAllElements();
  }
}






</script>

<template>
  <div class="processDemo1">
    <div class="tools">
      <span class="toolItemLabel">生产单号：</span>
      <Input class="toolItem" v-model:value="orderNo" style="width: 170px;" @change="orderNoChange" />

      <span class="toolItemLabel">机台选择：</span>
      <Select v-model:value="selectedMachineID" placeholder="请选择机台" :get-popup-container="getPopupContainer"
        style="width: 170px;" @change="machineChange">
        <SelectOption v-for="item in machineList" :key="item.id" :value="item.id">
          {{ item.name }}
        </SelectOption>
      </Select>

      <Button v-if="!isOptimizeing" @click="startPlace">开始优化</Button>
      
      <Button @click="drawSortingPlace">开料顺序</Button>
      <Button @click="drawCutPoint">下刀点</Button>
      <Button @click="getParserParams"> 解析器</Button>
      <BasicTable @register="registerTable" />
    </div>

    <div class="content">
      <div class="contentLeft">
        <div class="contentTools">

          <Select v-model:value="selectVal" class="plateSelect" :style="{ width: '200px', marginLeft: '10px' }"
            :options="plateSelectOptions" :field-names="{ label: 'goodsName', value: 'goodsId' }"
            @change="reDrawCanvas" />


          <Pagination v-model:current="paginationCurrent" @change="reDrawCanvas" :page-size="1" class="platePagination"
            :total="paginationCurrentAll" />
        </div>

        <div class="contentBtns">
          <Button class="contentBtn" @click="clearCanvas">清空</Button>
         

          <Textarea class="testData" v-model:value="testData1"></Textarea>
        </div>
      </div>

      <!-- 画布区域 -->
      <div class="contentMain" ref="canvasMain">
        <BoardView ref="canvas" class="BoardView" :width="canvasWidth" :height="canvasHeight" tabindex="0"
          @keydown="boardViewEvent('keyDown', $event)" @dblclick="boardViewEvent('CanvasEvent_dblclick', $event)"
          @mousedown="boardViewEvent('CanvasEvent_MouseDown', $event)"
          @mouseup="boardViewEvent('CanvasEvent_Mouseup', $event)"
          @mousemove="boardViewEvent('CanvasEvent_MouseMove', $event)"
          @wheel="boardViewEvent('CanvasEvent_Wheel', $event)"
          @contextmenu="boardViewEvent('CanvasEvent_RightClick', $event)" />
      </div>
    </div>
  </div>
</template>

<style>
.processDemo1 {
  height: 100%;
  width: 100%;
  display: flex;
  flex-direction: column;
  padding: 10px;
}

.tools {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}

.toolItemLabel {
  margin: auto 0;
}

.content {
  display: flex;
  flex-direction: row;
}

.contentLeft {
  display: flex;
  flex-direction: column;
  flex: 1;
}

.contentTools {
  display: flex;
  flex-direction: row;
}

.BoardView {
  border: 1px solid silver;
}

.contentBtns {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}

.contentBtn {
  margin: 6px 8px;
}

.testData {
  overflow: auto;
  min-height: 450px !important;
  background-color: #FFFFFF !important;
  color: #000000 !important;
}
</style>
