import { useEffect, useRef, useState } from 'react'
import QRect from '@/components/fabric/QRect'
import { findTopTwoIndexesByDistance, getCenterPoint, getDirection, getStartIndex, rearrangeArray } from '@/util/canvas-util'
import { useRecoilState } from 'recoil'

import {
  canvasSizeState,
  drewRoofCellsState,
  fontSizeState,
  roofPolygonArrayState,
  roofPolygonPatternArrayState,
  roofState,
  sortedPolygonArray,
  templateTypeState,
  wallState,
} from '@/store/canvasAtom'
import { QLine } from '@/components/fabric/QLine'
import { fabric } from 'fabric'
import { QPolygon } from '@/components/fabric/QPolygon'
import offsetPolygon from '@/util/qpolygon-utils'

export const Mode = {
  DRAW_LINE: 'drawLine', // 기준선 긋기모드`
  EDIT: 'edit',
  TEMPLATE: 'template',
  PATTERNA: 'patterna',
  PATTERNB: 'patternb',
  TEXTBOX: 'textbox',
  DRAW_RECT: 'drawRect',
  ROOF_PATTERN: 'roofPattern', //지붕패턴 모드
  ROOF_TRESTLE: 'roofTrestle', //지붕가대 모드
  FILL_CELLS: 'fillCells', //태양광셀 모드
  DEFAULT: 'default',
}

export function useMode() {
  const [mode, setMode] = useState()
  const points = useRef([])
  const historyPoints = useRef([])
  const historyLines = useRef([])
  const startPoint = useRef()
  const [canvas, setCanvas] = useState(null)
  const [zoom, setZoom] = useState(100)
  const [fontSize] = useRecoilState(fontSizeState)
  const [shape, setShape] = useState(0)
  const [sortedArray, setSortedArray] = useRecoilState(sortedPolygonArray)
  const [roof, setRoof] = useRecoilState(roofState)
  const [wall, setWall] = useRecoilState(wallState)

  const [endPoint, setEndPoint] = useState(null)

  const pointCount = useRef(0)

  const [roofPolygonPattern, setRoofPolygonPattern] = useRecoilState(roofPolygonPatternArrayState)
  const [roofPolygonArray, setRoofPolygonArray] = useRecoilState(roofPolygonArrayState)
  const [templateType, setTemplateType] = useRecoilState(templateTypeState)

  const [canvasSize] = useRecoilState(canvasSizeState)

  const [selectedCellRoofArray, setSelectedCellRoofArray] = useState([])
  const [drewRoofCells, setDrewRoofCells] = useRecoilState(drewRoofCellsState)

  useEffect(() => {
    // 이벤트 리스너 추가
    if (!canvas) {
      return
    }
    document.addEventListener('keydown', handleKeyDown)

    // 컴포넌트가 언마운트될 때 이벤트 리스너 제거
    return () => {
      document.removeEventListener('keydown', handleKeyDown)
    }
  }, [canvas]) // 빈 배열을 전달하여 컴포넌트가 마운트될 때만 실행되도록 함

  useEffect(() => {
    if (canvas?.getObjects().find((obj) => obj.name === 'connectLine')) {
      canvas?.remove(canvas?.getObjects().find((obj) => obj.name === 'connectLine'))
    }
    canvas?.off('mouse:move', (e) => addLineEndPointToMousePoint(e, endPoint))
    canvas?.off('mouse:move')
    canvas?.on('mouse:move', drawMouseLines)
    canvas?.off('mouse:out', removeMouseLines)
    canvas?.on('mouse:out', removeMouseLines)
    if (!endPoint) {
      return
    }

    canvas?.on('mouse:move', (e) => addLineEndPointToMousePoint(e, endPoint))
  }, [endPoint])

  const drawMouseLines = (e) => {
    // 현재 마우스 포인터의 위치를 가져옵니다.
    const pointer = canvas?.getPointer(e.e)

    // 기존에 그려진 가이드라인을 제거합니다.
    removeMouseLines()

    if (canvas?.getActiveObject()) {
      return
    }

    // 가로선을 그립니다.
    const horizontalLine = new fabric.Line([0, pointer.y, canvasSize.horizontal, pointer.y], {
      stroke: 'black',
      strokeWidth: 1,
      selectable: false,
      name: 'mouseLine',
    })

    // 세로선을 그립니다.
    const verticalLine = new fabric.Line([pointer.x, 0, pointer.x, canvasSize.vertical], {
      stroke: 'black',
      strokeWidth: 1,
      selectable: false,
      name: 'mouseLine',
    })

    // 선들을 캔버스에 추가합니다.
    canvas?.add(horizontalLine, verticalLine)

    // 캔버스를 다시 그립니다.
    canvas?.renderAll()
  }

  useEffect(() => {
    if (pointCount.current <= 2) {
      removeGuideLines()
      return
    }
    drawGuideLines()
  }, [pointCount.current])

  const removeGuideLines = () => {
    const guideLines = canvas?._objects.filter((obj) => obj.name === 'guideLine')
    guideLines?.forEach((item) => canvas?.remove(item))
  }

  const drawGuideLines = () => {
    // 이름이 guideLine인 가이드라인을 제거합니다.
    removeGuideLines()

    const arrivalX = startPoint.current?.left
    const arrivalY = startPoint.current?.top

    const lastX = endPoint?.left
    const lastY = endPoint?.top

    if (lastX === arrivalX || lastY === arrivalY) {
      // 둘중 하나라도 같으면 guideLine은 한개만 생성
      const guideLine = new QLine([lastX, lastY, arrivalX, arrivalY], {
        fontSize: fontSize,
        stroke: 'black',
        strokeWidth: 1,
        strokeDashArray: [1, 1, 1],
      })
      guideLine.name = 'guideLine'
      canvas?.add(guideLine)
    } else {
      const guideLine1 = new QLine([lastX, lastY, lastX, arrivalY], {
        fontSize: fontSize,
        stroke: 'black',
        strokeWidth: 1,
        strokeDashArray: [1, 1, 1],
      })

      const guideLine2 = new QLine([guideLine1.x2, guideLine1.y2, arrivalX, arrivalY], {
        fontSize: fontSize,
        stroke: 'black',
        strokeWidth: 1,
        strokeDashArray: [1, 1, 1],
      })

      guideLine1.name = 'guideLine'
      guideLine2.name = 'guideLine'

      canvas?.add(guideLine1)
      canvas?.add(guideLine2)
    }
  }

  /**
   * 마우스 포인터의 가이드라인을 제거합니다.
   */
  const removeMouseLines = () => {
    if (canvas?._objects.length > 0) {
      const mouseLines = canvas?._objects.filter((obj) => obj.name === 'mouseLine')
      mouseLines.forEach((item) => canvas?.remove(item))
    }
    canvas?.renderAll()
  }

  const addLineEndPointToMousePoint = (e, endPoint) => {
    if (canvas?.getObjects().find((obj) => obj.name === 'connectLine')) {
      canvas?.remove(canvas?.getObjects().find((obj) => obj.name === 'connectLine'))
    }

    if (!endPoint) {
      return
    }

    const pointer = canvas?.getPointer(e.e)

    // 마우스 포인터 위치랑 endPoint를 연결하는 line 생성
    const line = new fabric.Line([endPoint.left, endPoint.top, pointer.x, pointer.y], {
      stroke: 'black',
      strokeWidth: 1,
      selectable: false,
    })

    line.set({ name: 'connectLine' })

    canvas?.add(line)
    canvas?.renderAll()
  }

  const addEvent = (mode) => {
    switch (mode) {
      case 'drawLine':
        drawLineMode()
        break
      case 'edit':
        editMode()
        break
      case 'template':
        templateMode()
        break
      case 'patterna':
        applyTemplateA()
        break
      case 'patternb':
        applyTemplateB()
        break
      case 'textbox':
        textboxMode()
        break
      case 'drawRect':
        drawRectMode()
        break
      case 'roofPattern':
        makeRoofPatternPolygon()
        break
      case 'roofTrestle':
        makeRoofTrestle()
        break
      case 'fillCells':
        makeRoofFillCells()
        break
      case 'default':
        canvas?.off('mouse:down')
        break
    }
  }

  const keyValid = () => {
    if (points.current.length === 0) {
      alert('시작점을 선택해주세요')
      return false
    }
    return true
  }

  const drawCircleAndLine = (verticalLength, horizontalLength) => {
    const circle = new fabric.Circle({
      radius: 5,
      fill: 'transparent', // 원 안을 비웁니다.
      stroke: 'black', // 원 테두리 색상을 검은색으로 설정합니다.
      left: points.current[points.current.length - 1].left + horizontalLength - 5,
      top: points.current[points.current.length - 1].top + verticalLength - 5,
      originX: 'center',
      originY: 'center',
      selectable: false,
    })

    historyPoints.current.push(circle)
    points.current.push(circle)
    canvas?.add(circle)
    canvas?.renderAll()

    // length 값이 숫자가 아닌 경우
    if (isNaN(length) || Math.max(Math.abs(verticalLength), Math.abs(horizontalLength)) === 0) {
      //마지막 추가 된 points 제거합니다.

      const lastPoint = historyPoints.current[historyPoints.current.length - 1]

      canvas?.remove(lastPoint)

      historyPoints.current.pop()
      points.current.pop()
      return
    }

    const line = new QLine(
      [points.current[0].left, points.current[0].top, points.current[0].left + horizontalLength, points.current[0].top + verticalLength],
      {
        stroke: 'black',
        strokeWidth: 2,
        selectable: false,
        viewLengthText: true,
        direction: getDirection(points.current[0], points.current[1]),
        fontSize: fontSize,
      },
    )

    pushHistoryLine(line)

    // 라인의 끝에 점을 추가합니다.
    const endPointCircle = new fabric.Circle({
      radius: 1,
      fill: 'transparent', // 원 안을 비웁니다.
      stroke: 'black', // 원 테두리 색상을 검은색으로 설정합니다.
      left: points.current[0].left + horizontalLength,
      top: points.current[0].top + verticalLength,
      originX: 'center',
      originY: 'center',
      selectable: false,
    })

    canvas?.add(endPointCircle)

    historyPoints.current.push(endPointCircle)

    points.current.forEach((point) => {
      canvas?.remove(point)
    })

    setEndPoint(endPointCircle)
    pointCount.current = pointCount.current + 1

    points.current = [endPointCircle]

    canvas?.renderAll()
  }

  const handleKeyDown = (e) => {
    switch (e.key) {
      case 'ArrowDown': {
        if (!keyValid()) {
          return
        }
        const verticalLength = Number(prompt('길이를 입력하세요:'))
        const horizontalLength = 0

        drawCircleAndLine(verticalLength, horizontalLength)

        break
      }
      case 'ArrowUp': {
        if (!keyValid()) {
          return
        }
        const verticalLength = -Number(prompt('길이를 입력하세요:'))
        const horizontalLength = 0

        drawCircleAndLine(verticalLength, horizontalLength)

        break
      }
      case 'ArrowLeft': {
        if (!keyValid()) {
          return
        }
        const verticalLength = 0
        const horizontalLength = -Number(prompt('길이를 입력하세요:'))

        drawCircleAndLine(verticalLength, horizontalLength)

        break
      }
      case 'ArrowRight': {
        if (!keyValid()) {
          return
        }

        const verticalLength = 0
        const horizontalLength = Number(prompt('길이를 입력하세요:'))

        drawCircleAndLine(verticalLength, horizontalLength)

        break
      }

      case 'Enter': {
        const result = prompt('입력하세요 (a(A패턴),b(B패턴),t(지붕))')

        switch (result) {
          case 'a':
            applyTemplateA()
            break
          case 'b':
            applyTemplateB()
            break
          case 't':
            templateMode()
            break
        }
      }
    }
  }

  const changeMode = (canvas, mode) => {
    setEndPoint(null)
    pointCount.current = 0

    setMode(mode)
    // mode변경 시 이전 이벤트 제거
    setCanvas(canvas)
    canvas?.off('mouse:down')

    addEvent(mode)
  }

  const editMode = () => {
    canvas?.on('mouse:down', function (options) {
      const pointer = canvas?.getPointer(options.e)
      const circle = new fabric.Circle({
        radius: 5,
        fill: 'transparent', // 원 안을 비웁니다.
        stroke: 'red', // 원 테두리 색상을 검은색으로 설정합니다.
        left: pointer.x - 5,
        top: pointer.y - 5,
        originX: 'center',
        originY: 'center',
        selectable: false,
      })
      if (!startPoint.current) {
        startPoint.current = circle
        pointCount.current = pointCount.current + 1
      }

      setEndPoint(circle)

      historyPoints.current.push(circle)
      points.current.push(circle)
      canvas?.add(circle)

      if (points.current.length === 2) {
        const length = Number(prompt('길이를 입력하세요:'))

        // length 값이 숫자가 아닌 경우
        if (isNaN(length) || length === 0) {
          //마지막 추가 된 points 제거합니다.

          const lastPoint = historyPoints.current[historyPoints.current.length - 1]

          canvas?.remove(lastPoint)

          historyPoints.current.pop()
          points.current.pop()
          return
        }

        if (length) {
          const vector = {
            x: points.current[1].left - points.current[0].left,
            y: points.current[1].top - points.current[0].top,
          }
          const slope = Math.abs(vector.y / vector.x) // 기울기 계산

          let scaledVector
          if (slope >= 1) {
            // 기울기가 1 이상이면 x축 방향으로 그림
            scaledVector = {
              x: 0,
              y: vector.y >= 0 ? Number(length) : -Number(length),
            }
          } else {
            // 기울기가 1 미만이면 y축 방향으로 그림
            scaledVector = {
              x: vector.x >= 0 ? Number(length) : -Number(length),
              y: 0,
            }
          }

          const verticalLength = scaledVector.y
          const horizontalLength = scaledVector.x

          drawCircleAndLine(verticalLength, horizontalLength)
        }
      }

      canvas?.renderAll()
    })
  }

  const pushHistoryLine = (line) => {
    if (historyLines.current.length > 0 && historyLines.current[historyLines.current.length - 1].direction === line.direction) {
      // 같은 방향의 선이 두 번 연속으로 그려지면 이전 선을 제거하고, 새로운 선과 merge한다.

      const lastLine = historyLines.current.pop()
      canvas?.remove(lastLine)

      const mergedLine = new QLine([lastLine.x1, lastLine.y1, line.x2, line.y2], {
        stroke: 'black',
        strokeWidth: 2,
        selectable: false,
        viewLengthText: true,
        direction: lastLine.direction,
        fontSize: fontSize,
      })
      historyLines.current.push(mergedLine)
      canvas?.add(mergedLine)
    } else {
      historyLines.current.push(line)
      canvas?.add(line)
    }
  }

  /**
   * 마우스로 그린 점 기준으로 외벽선을 완성시켜준다.
   * makePolygon 함수에 포함되어있던 내용을 다른 템플릿 적용에서도 사용할수 있도록 함수로 대체
   */
  const drawWallPolygon = () => {
    const firstPoint = historyPoints.current[0]
    const lastPoint = historyPoints.current[historyPoints.current.length - 1]
    historyPoints.current.forEach((point) => {
      canvas?.remove(point)
    })
    drawLineWithLength(lastPoint, firstPoint)
    points.current = []
    historyPoints.current = []

    // handleOuterlines()
    const wall = makePolygon()
    setWall(wall)

    return wall
  }

  const templateMode = () => {
    changeMode(canvas, Mode.EDIT)

    if (historyPoints.current.length >= 4) {
      const wall = drawWallPolygon()
      handleOuterlinesTest2(wall)
      /*setWall(wall)
      roof.drawHelpLine()*/
    }
  }

  const textboxMode = () => {
    canvas?.on('mouse:down', function (options) {
      if (canvas?.getActiveObject()?.type === 'textbox') return
      const pointer = canvas?.getPointer(options.e)

      const textbox = new fabric.Textbox('텍스트를 입력하세요', {
        left: pointer.x,
        top: pointer.y,
        width: 150, // 텍스트박스의 너비를 설정합니다.
        fontSize: fontSize, // 텍스트의 크기를 설정합니다.
      })

      canvas?.add(textbox)
      canvas?.setActiveObject(textbox) // 생성된 텍스트박스를 활성 객체로 설정합니다.
      canvas?.renderAll()
      // textbox가 active가 풀린 경우 editing mode로 변경
      textbox?.on('editing:exited', function () {
        changeMode(canvas, Mode.EDIT)
      })
    })
  }

  const drawLineMode = () => {
    canvas?.on('mouse:down', function (options) {
      const pointer = canvas?.getPointer(options.e)

      const line = new QLine(
        [pointer.x, 0, pointer.x, canvas.height], // y축에 1자 선을 그립니다.
        {
          stroke: 'black',
          strokeWidth: 2,
          viewLengthText: true,
          selectable: false,
          fontSize: fontSize,
        },
      )

      canvas?.add(line)
      canvas?.renderAll()
    })
  }

  const drawRectMode = () => {
    let rect, isDown, origX, origY
    canvas.on('mouse:down', function (o) {
      isDown = true
      const pointer = canvas.getPointer(o.e)
      origX = pointer.x
      origY = pointer.y
      rect = new fabric.Rect({
        left: origX,
        top: origY,
        originX: 'left',
        originY: 'top',
        width: pointer.x - origX,
        height: pointer.y - origY,
        angle: 0,
        fill: 'transparent',
        stroke: 'black',
        transparentCorners: false,
      })
      canvas.add(rect)
    })

    canvas.on('mouse:move', function (o) {
      if (!isDown) return
      const pointer = canvas.getPointer(o.e)
      if (origX > pointer.x) {
        rect.set({ left: Math.abs(pointer.x) })
      }
      if (origY > pointer.y) {
        rect.set({ top: Math.abs(pointer.y) })
      }

      rect.set({ width: Math.abs(origX - pointer.x) })
      rect.set({ height: Math.abs(origY - pointer.y) })
    })

    canvas.on('mouse:up', function (o) {
      const pointer = canvas.getPointer(o.e)
      const qRect = new QRect({
        left: origX,
        top: origY,
        originX: 'left',
        originY: 'top',
        width: pointer.x - origX,
        height: pointer.y - origY,
        angle: 0,
        viewLengthText: true,
        fill: 'transparent',
        stroke: 'black',
        transparentCorners: false,
        fontSize: fontSize,
      })
      canvas.remove(rect)
      canvas.add(qRect)
      isDown = false
    })
  }

  /**
   * 두 점을 연결하는 선과 길이를 그립니다.
   * a : 시작점, b : 끝점
   */
  const drawLineWithLength = (a, b) => {
    if (!a || !b) {
      return
    }
    const line = new QLine([a.left, a.top, b.left, b.top], {
      stroke: 'black',
      strokeWidth: 2,
      selectable: false,
      viewLengthText: true,
      direction: getDirection(a, b),
      fontSize: fontSize,
    })
    pushHistoryLine(line)

    canvas?.renderAll()
  }

  const makePolygon = (otherLines) => {
    // 캔버스에서 모든 라인 객체를 찾습니다.
    const lines = otherLines || historyLines.current

    if (!otherLines) {
      //외각선 기준
      const topIndex = findTopTwoIndexesByDistance(sortedArray) //배열중에 큰 2값을 가져옴 TODO: 나중에는 인자로 받아서 다각으로 수정 해야됨

      //일단 배열 6개 짜리 기준의 선 번호
      if (topIndex[0] === 4) {
        if (topIndex[1] === 5) {
          //1번
          setShape(1)
        }
      } else if (topIndex[0] === 1) {
        //4번
        if (topIndex[1] === 2) {
          setShape(4)
        }
      } else if (topIndex[0] === 0) {
        if (topIndex[1] === 1) {
          //2번
          setShape(2)
        } else if (topIndex[1] === 5) {
          setShape(3)
        }
      }

      historyLines.current = []
    }

    // 각 라인의 시작점과 끝점을 사용하여 다각형의 점 배열을 생성합니다.
    const points = lines.map((line) => ({ x: line.x1, y: line.y1 }))

    // 모든 라인 객체를 캔버스에서 제거합니다.
    lines.forEach((line) => {
      canvas?.remove(line)
    })

    // 점 배열을 사용하여 새로운 다각형 객체를 생성합니다.
    const polygon = new QPolygon(
      points,
      {
        stroke: 'black',
        fill: 'transparent',
        viewLengthText: true,
        fontSize: fontSize,
      },
      canvas,
    )

    // 새로운 다각형 객체를 캔버스에 추가합니다.
    canvas.add(polygon)

    // 캔버스를 다시 그립니다.
    if (!otherLines) {
      // polygon.fillCell()
      canvas?.renderAll()
      // polygon.setViewLengthText(false)
      setMode(Mode.DEFAULT)
    }

    return polygon
  }

  /**
   * 해당 캔버스를 비운다.
   */
  const handleClear = () => {
    canvas?.clear()
    startPoint.current = null
    setEndPoint(null)
    points.current = []
    historyPoints.current = []
    historyLines.current = []
  }

  const zoomIn = () => {
    canvas?.setZoom(canvas.getZoom() + 0.1)
    setZoom(Math.round(zoom + 10))
  }

  const zoomOut = () => {
    canvas?.setZoom(canvas.getZoom() - 0.1)
    setZoom(Math.ceil(zoom - 10))
  }

  const handleOuterlines = () => {
    const newOuterlines = []
    for (let i = 0; i < historyLines.current.length; i++) {
      const next = historyLines.current[i + 1]
      const prev = historyLines.current[i - 1] ?? historyLines.current[historyLines.current.length - 1]
      if (next) {
        if (next.direction === 'right') {
          // 다름 라인이 오른쪽으로 이동
          if (historyLines.current[i].direction === 'top') {
            if (prev.direction !== 'right') {
              if (historyLines.current.length === 4) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 - 50,
                  y1: historyLines.current[i].y1 + 50,
                  x2: historyLines.current[i].x2 - 50,
                  y2: historyLines.current[i].y2 - 50,
                })
              } else if (historyLines.current.length === 6) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 - 50,
                  y1: historyLines.current[i].y1 + 50,
                  x2: historyLines.current[i].x2 - 50,
                  y2: historyLines.current[i].y2 - 50,
                })
              } else if (historyLines.current.length === 8) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 + 50,
                  y1: historyLines.current[i].y1 - 50,
                  x2: historyLines.current[i].x2 + 50,
                  y2: historyLines.current[i].y2 + 50,
                })
              }
            } else {
              newOuterlines.push({
                x1: historyLines.current[i].x1 + 50,
                y1: historyLines.current[i].y1 + 50,
                x2: historyLines.current[i].x2 + 50,
                y2: historyLines.current[i].y2 + 50,
              })
            }
          } else {
            // bottom
            if (prev?.direction !== 'right') {
              if (historyLines.current.length === 4) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 - 50,
                  y1: historyLines.current[i].y1 - 50,
                  x2: historyLines.current[i].x2 - 50,
                  y2: historyLines.current[i].y2 + 50,
                })
              } else if (historyLines.current.length === 6) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 - 50,
                  y1: historyLines.current[i].y1 - 50,
                  x2: historyLines.current[i].x2 - 50,
                  y2: historyLines.current[i].y2 + 50,
                })
              } else if (historyLines.current.length === 8) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 + 50,
                  y1: historyLines.current[i].y1 + 50,
                  x2: historyLines.current[i].x2 + 50,
                  y2: historyLines.current[i].y2 - 50,
                })
              }
            } else {
              newOuterlines.push({
                x1: historyLines.current[i].x1 - 50,
                y1: historyLines.current[i].y1 + 50,
                x2: historyLines.current[i].x2 - 50,
                y2: historyLines.current[i].y2 + 50,
              })
            }
          }
        } else if (next.direction === 'left') {
          if (historyLines.current[i].direction === 'top') {
            if (prev?.direction !== 'left') {
              if (historyLines.current.length === 4) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 + 50,
                  y1: historyLines.current[i].y1 + 50,
                  x2: historyLines.current[i].x2 + 50,
                  y2: historyLines.current[i].y2 - 50,
                })
              } else if (historyLines.current.length === 6) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 + 50,
                  y1: historyLines.current[i].y1 + 50,
                  x2: historyLines.current[i].x2 + 50,
                  y2: historyLines.current[i].y2 - 50,
                })
              } else if (historyLines.current.length === 8) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 - 50,
                  y1: historyLines.current[i].y1 - 50,
                  x2: historyLines.current[i].x2 - 50,
                  y2: historyLines.current[i].y2 + 50,
                })
              }
            } else {
              newOuterlines.push({
                x1: historyLines.current[i].x1 + 50,
                y1: historyLines.current[i].y1 - 50,
                x2: historyLines.current[i].x2 + 50,
                y2: historyLines.current[i].y2 - 50,
              })
            }
          } else {
            // bottom
            if (prev?.direction !== 'left') {
              if (historyLines.current.length === 4) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 + 50,
                  y1: historyLines.current[i].y1 - 50,
                  x2: historyLines.current[i].x2 + 50,
                  y2: historyLines.current[i].y2 + 50,
                })
              } else if (historyLines.current.length === 6) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 + 50,
                  y1: historyLines.current[i].y1 - 50,
                  x2: historyLines.current[i].x2 + 50,
                  y2: historyLines.current[i].y2 + 50,
                })
              } else if (historyLines.current.length === 8) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 - 50,
                  y1: historyLines.current[i].y1 + 50,
                  x2: historyLines.current[i].x2 - 50,
                  y2: historyLines.current[i].y2 - 50,
                })
              }
            } else {
              newOuterlines.push({
                x1: historyLines.current[i].x1 - 50,
                y1: historyLines.current[i].y1 - 50,
                x2: historyLines.current[i].x2 - 50,
                y2: historyLines.current[i].y2 - 50,
              })
            }
          }
        } else if (next.direction === 'top') {
          if (historyLines.current[i].direction === 'right') {
            if (prev?.direction !== 'top') {
              if (historyLines.current.length === 4) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 - 50,
                  y1: historyLines.current[i].y1 + 50,
                  x2: historyLines.current[i].x2 + 50,
                  y2: historyLines.current[i].y2 + 50,
                })
              } else if (historyLines.current.length === 6) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 - 50,
                  y1: historyLines.current[i].y1 + 50,
                  x2: historyLines.current[i].x2 + 50,
                  y2: historyLines.current[i].y2 + 50,
                })
              } else if (historyLines.current.length === 8) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 + 50,
                  y1: historyLines.current[i].y1 - 50,
                  x2: historyLines.current[i].x2 - 50,
                  y2: historyLines.current[i].y2 - 50,
                })
              }
            } else {
              newOuterlines.push({
                x1: historyLines.current[i].x1 + 50,
                y1: historyLines.current[i].y1 + 50,
                x2: historyLines.current[i].x2 + 50,
                y2: historyLines.current[i].y2 + 50,
              })
            }
          } else {
            // left
            if (prev?.direction !== 'top') {
              if (historyLines.current.length === 4) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 + 50,
                  y1: historyLines.current[i].y1 + 50,
                  x2: historyLines.current[i].x2 - 50,
                  y2: historyLines.current[i].y2 + 50,
                })
              } else if (historyLines.current.length === 6) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 + 50,
                  y1: historyLines.current[i].y1 + 50,
                  x2: historyLines.current[i].x2 - 50,
                  y2: historyLines.current[i].y2 + 50,
                })
              } else if (historyLines.current.length === 8) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 - 50,
                  y1: historyLines.current[i].y1 - 50,
                  x2: historyLines.current[i].x2 + 50,
                  y2: historyLines.current[i].y2 - 50,
                })
              }
            } else {
              newOuterlines.push({
                x1: historyLines.current[i].x1 + 50,
                y1: historyLines.current[i].y1 - 50,
                x2: historyLines.current[i].x2 + 50,
                y2: historyLines.current[i].y2 - 50,
              })
            }
          }
        } else if (next.direction === 'bottom') {
          if (historyLines.current[i].direction === 'right') {
            if (prev?.direction !== 'bottom') {
              if (historyLines.current.length === 4) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 - 50,
                  y1: historyLines.current[i].y1 - 50,
                  x2: historyLines.current[i].x2 + 50,
                  y2: historyLines.current[i].y2 - 50,
                })
              } else if (historyLines.current.length === 6) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 - 50,
                  y1: historyLines.current[i].y1 - 50,
                  x2: historyLines.current[i].x2 + 50,
                  y2: historyLines.current[i].y2 - 50,
                })
              } else if (historyLines.current.length === 8) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 + 50,
                  y1: historyLines.current[i].y1 + 50,
                  x2: historyLines.current[i].x2 - 50,
                  y2: historyLines.current[i].y2 + 50,
                })
              }
            } else {
              newOuterlines.push({
                x1: historyLines.current[i].x1 - 50,
                y1: historyLines.current[i].y1 + 50,
                x2: historyLines.current[i].x2 - 50,
                y2: historyLines.current[i].y2 + 50,
              })
            }
          } else {
            // left
            if (prev.direction !== 'bottom') {
              if (historyLines.current.length === 4) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 + 50,
                  y1: historyLines.current[i].y1 - 50,
                  x2: historyLines.current[i].x2 - 50,
                  y2: historyLines.current[i].y2 - 50,
                })
              } else if (historyLines.current.length === 6) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 + 50,
                  y1: historyLines.current[i].y1 - 50,
                  x2: historyLines.current[i].x2 - 50,
                  y2: historyLines.current[i].y2 - 50,
                })
              } else if (historyLines.current.length === 8) {
                newOuterlines.push({
                  x1: historyLines.current[i].x1 - 50,
                  y1: historyLines.current[i].y1 + 50,
                  x2: historyLines.current[i].x2 + 50,
                  y2: historyLines.current[i].y2 + 50,
                })
              }
            } else {
              newOuterlines.push({
                x1: historyLines.current[i].x1 - 50,
                y1: historyLines.current[i].y1 - 50,
                x2: historyLines.current[i].x2 + 50,
                y2: historyLines.current[i].y2 - 50,
              })
            }
          }
        }
      } else {
        const tmp = newOuterlines[newOuterlines.length - 1]
        newOuterlines.push({
          x1: tmp.x2,
          y1: tmp.y2,
          x2: newOuterlines[0].x1,
          y2: newOuterlines[0].y1,
        })
      }
    }

    makePolygon(newOuterlines)
  }

  /**
   *벽 지붕 외곽선 생성
   */
  const handleOuterlinesTest = (polygon, offsetInputX, offsetInputY = 0) => {
    let offsetPoints = []
    const originalMax = 71
    const transformedMax = 100

    offsetInputY = offsetInputY !== 0 ? offsetInputY : offsetInputX

    const offsetX = (offsetInputX / transformedMax) * originalMax * 2
    const offsetY = (offsetInputY / transformedMax) * originalMax * 2

    const sortedIndex = getStartIndex(polygon.lines)
    let tmpArraySorted = rearrangeArray(polygon.lines, sortedIndex)

    if (tmpArraySorted[0].direction === 'right') {
      //시계방향
      tmpArraySorted = tmpArraySorted.reverse() //그럼 배열을 거꾸로 만들어서 무조건 반시계방향으로 배열 보정
    }

    setSortedArray(tmpArraySorted) //recoil에 넣음

    const points = tmpArraySorted.map((line) => ({
      x: line.x1,
      y: line.y1,
    }))

    for (var i = 0; i < points.length; i++) {
      var prev = points[(i - 1 + points.length) % points.length]
      var current = points[i]
      var next = points[(i + 1) % points.length]

      // 두 벡터 계산 (prev -> current, current -> next)
      var vector1 = { x: current.x - prev.x, y: current.y - prev.y }
      var vector2 = { x: next.x - current.x, y: next.y - current.y }

      // 벡터의 길이 계산
      var length1 = Math.sqrt(vector1.x * vector1.x + vector1.y * vector1.y)
      var length2 = Math.sqrt(vector2.x * vector2.x + vector2.y * vector2.y)

      // 벡터를 단위 벡터로 정규화
      var unitVector1 = { x: vector1.x / length1, y: vector1.y / length1 }
      var unitVector2 = { x: vector2.x / length2, y: vector2.y / length2 }

      // 법선 벡터 계산 (왼쪽 방향)
      var normal1 = { x: -unitVector1.y, y: unitVector1.x }
      var normal2 = { x: -unitVector2.y, y: unitVector2.x }

      // 법선 벡터 평균 계산
      var averageNormal = {
        x: (normal1.x + normal2.x) / 2,
        y: (normal1.y + normal2.y) / 2,
      }

      // 평균 법선 벡터를 단위 벡터로 정규화
      var lengthNormal = Math.sqrt(averageNormal.x * averageNormal.x + averageNormal.y * averageNormal.y)
      var unitNormal = {
        x: averageNormal.x / lengthNormal,
        y: averageNormal.y / lengthNormal,
      }

      // 오프셋 적용
      var offsetPoint = {
        x1: current.x + unitNormal.x * offsetX,
        y1: current.y + unitNormal.y * offsetY,
      }

      offsetPoints.push(offsetPoint)
    }

    return makePolygon(offsetPoints)
  }

  /**
   *벽 지붕 외곽선 생성 polygon을 입력받아 만들기
   */
  const handleOuterlinesTest2 = (polygon, offset = 71) => {
    const offsetPoints = offsetPolygon(polygon.points, 50)

    const roof = makePolygon(
      offsetPoints.map((point) => {
        return { x1: point.x, y1: point.y }
      }),
    )
    roof.setWall(polygon)
    setRoof(roof)

    roof.drawHelpLine()
    roof.divideLine()
  }

  const togglePolygonLine = (obj) => {
    const rtnLines = []
    if (obj.type === 'QPolygon') {
      const points = obj.getCurrentPoints()
      points.forEach((point, index) => {
        const nextPoint = points[(index + 1) % points.length] // 마지막 점이면 첫 번째 점으로 연결
        const line = new QLine([point.x, point.y, nextPoint.x, nextPoint.y], {
          stroke: 'black',
          strokeWidth: 2,
          selectable: false,
          fontSize: fontSize, // fontSize는 필요에 따라 조정
          parent: obj,
        })
        obj.visible = false
        canvas.add(line)
        rtnLines.push(line)
      })

      canvas?.renderAll()
    }
    if (obj.type === 'QLine') {
      const parent = obj.parent
      canvas
        ?.getObjects()
        .filter((obj) => obj.parent === parent)
        .forEach((obj) => {
          rtnLines.push(obj)
          canvas.remove(obj)
        })

      parent.visible = true
      canvas?.renderAll()
    }
    return rtnLines
  }

  const applyTemplateA = () => {
    changeMode(canvas, Mode.EDIT)
    const polygon = drawWallPolygon()
    handleClear()

    if (polygon.lines.length === 4) {
      //4각형
      handleOuterLineTemplateA4Points(polygon)
    } else if (polygon.lines.length === 6) {
      //6각형
      handleOuterLineTemplateA6Points(polygon)
    } else if (polygon.lines.length === 8) {
      handleOuterLineTemplateA8Points(polygon)
    }
    setTemplateType(2)
  }

  const handleOuterLineTemplateA4Points = (polygon) => {
    const edge = 20
    const eaves = 50

    // 폴리곤의 각 변을 선으로 생성
    const createLine = (start, end, stroke, property) =>
      new QLine([start.x, start.y, end.x, end.y], {
        stroke,
        strokeWidth: 5,
        property,
        fontSize: 14,
      })

    const lines = polygon.points.map((start, i) => {
      const end = polygon.points[(i + 1) % polygon.points.length]
      const line = createLine(start, end, '#A0D468', 'normal')
      canvas.add(line)
      return line
    })

    let edgeIndexArray = []
    let normalIndexArray = []

    lines.forEach((line, i) => {
      if (i % 2 === 0) {
        line.set('stroke', 'skyblue').set('property', 'edge')
        edgeIndexArray.push(i)
      } else {
        normalIndexArray.push(i)
      }
      canvas.add(line)
    })

    const centerPointX = (lines[1].x1 + lines[1].x2) / 2
    const centerPointY = (lines[0].y1 + lines[0].y2) / 2
    const horiCenterHalfLine = (lines[1].x2 - lines[1].x1) / 2

    const createCenterLine = (x1, y1, x2, y2, stroke, strokeWidth, property, dashArray = []) =>
      new QLine([x1, y1, x2, y2], {
        stroke,
        strokeWidth,
        property,
        fontSize: 14,
        strokeDashArray: dashArray,
      })

    const vertCenterLine = createCenterLine(centerPointX, lines[0].y1 - edge, centerPointX, lines[0].y2 + edge, 'blue', 4, 'center')
    canvas.add(vertCenterLine)

    const horiCenterLineLeft = createCenterLine(
      lines[1].x1 - eaves,
      centerPointY,
      lines[1].x1 + horiCenterHalfLine,
      centerPointY,
      'black',
      2,
      'center',
      [5, 5],
    )
    canvas.add(horiCenterLineLeft)

    const horiCenterLineRight = createCenterLine(
      horiCenterLineLeft.x2,
      centerPointY,
      horiCenterLineLeft.x2 + horiCenterHalfLine + eaves,
      centerPointY,
      'black',
      2,
      'center',
      [5, 5],
    )
    canvas.add(horiCenterLineRight)

    const drawArray = lines
      .map((line) => {
        if (line.x1 === line.x2 && line.y1 < line.y2) {
          return [{ x1: line.x1 - eaves, y1: line.y1 - edge, x2: line.x1 - eaves, y2: line.y2 + edge }]
        } else if (line.x1 === line.x2 && line.y1 > line.y2) {
          return [{ x1: line.x1 + eaves, y1: line.y1 + edge, x2: line.x1 + eaves, y2: line.y2 - edge }]
        } else if (line.x1 < line.x2 && line.y1 === line.y2) {
          return [
            { x1: line.x1 - eaves, y1: line.y1 + edge, x2: line.x1 + horiCenterHalfLine, y2: line.y2 + edge },
            {
              x1: line.x1 + horiCenterHalfLine,
              y1: line.y1 + edge,
              x2: line.x1 + horiCenterHalfLine + horiCenterHalfLine + eaves,
              y2: line.y2 + edge,
            },
          ]
        } else if (line.x1 > line.x2 && line.y1 === line.y2) {
          return [
            { x1: line.x2 - eaves, y1: line.y1 - edge, x2: line.x2 + horiCenterHalfLine, y2: line.y2 - edge },
            {
              x1: line.x2 + horiCenterHalfLine,
              y1: line.y1 - edge,
              x2: line.x2 + horiCenterHalfLine + horiCenterHalfLine + eaves,
              y2: line.y2 - edge,
            },
          ]
        }
        return []
      })
      .flat()

    drawArray.forEach((line) => {
      const outLine = createLine({ x: line.x1, y: line.y1 }, { x: line.x2, y: line.y2 }, 'blue', 'normal')
      canvas.add(outLine)
    })
  }

  //탬플릿A 적용
  const handleOuterLineTemplateA6Points = (polygon) => {
    let lines = []
    let outLines = []

    let halfLength = 0

    const dashedCenterLineOpt = {
      stroke: 'black',
      strokeWidth: 1,
      property: 'centerLine',
      strokeDashArray: [10, 5],
      fontSize: 14,
    }

    const centerLineOpt = {
      stroke: 'blue',
      strokeWidth: 1,
      property: 'bigHoriCenter',
      fontSize: 14,
    }

    // 폴리곤의 각 변을 선으로 생성
    for (let i = 0; i < polygon.points.length; i++) {
      const start = polygon.points[i]
      const end = polygon.points[(i + 1) % polygon.points.length] // 다음 점, 마지막 점의 경우 첫 점으로

      const line = new QLine([start.x, start.y, end.x, end.y], {
        stroke: '#A0D468',
        strokeWidth: 2,
        property: 'normal',
        fontSize: 14,
      })

      // 선을 배열에 추가
      lines.push(line)
      canvas.add(line)
    }

    let highLineLength = 0
    let lowLineLength = 0

    let prevHighIndex = 0
    let prevHighLength = 0

    let prevLowIndex = 0
    let prevLowLength = 0

    let edgeIndexArray = []
    let normalIndexArray = []

    for (let i = 0; i < lines.length; i++) {
      let line = lines[i]

      if (!(i % 2) == 0) {
        //홀수일떄
        line.line.set('stroke', 'skyblue').set('property', 'egde')
        let length = Math.abs(line.get('x1') - line.get('x2')) + Math.abs(line.get('y1') - line.get('y2'))

        if (length > prevHighLength) {
          //잴긴거 찾음
          prevHighIndex = i
          prevHighLength = length
          highLineLength = length
        }

        if (prevLowLength === 0 || length <= prevLowLength) {
          //최초에는 없어서 한번 넣음
          prevLowIndex = i
          prevLowLength = length
          lowLineLength = length
        }

        edgeIndexArray.push(i)
      } else {
        normalIndexArray.push(i)
      }

      // 캔버스에 선 추가
      canvas.add(line)
    }

    let prevDirecArray //긴선 앞배열
    let nextDirecArray //긴선 뒷배열
    let horizontalDirection //뽈록이 좌우 방향

    if (prevHighIndex === 1) {
      //카라바 기준 1과 5밖에 없음
      prevDirecArray = lines[prevHighIndex - 1]
      nextDirecArray = lines[prevHighIndex + 1]

      //밑에쪽이 긴 방향
      horizontalDirection = prevDirecArray.height > nextDirecArray.height ? 'left' : 'right'
    } else {
      prevDirecArray = lines[prevHighIndex - 1]
      nextDirecArray = lines[0]

      //위에가 긴 방향
      horizontalDirection = prevDirecArray.height > nextDirecArray.height ? 'right' : 'left'
    }

    const edge = 20 //케라바
    const eaves = 50 //처마
    let firstLine = lines[1]
    let secondLine = lines[3]
    let lastLine = lines[5]
    let vertCenterLine
    let secondVertCenterLine
    let templatePolygonObj = {}
    let roofPatternPolygonArray = []

    let bigRoofPolygon = []
    let middleRoofPolygon = []
    let smallRoofPolygon = []

    if (prevHighIndex === 1) {
      if (horizontalDirection === 'left') {
        //배열 순서대로 뒤에꺼를 찾아서 계산한다
        const firstSubLine = lines[2]
        const middleSubLine = lines[4]

        //ㄴ자 일경우
        //긴면 세로선 그리기
        let vertCenterPoint = (firstLine.x1 + firstLine.x2) / 2 //가장 긴선 중앙선 가운데 점
        vertCenterLine = new QLine(
          [
            vertCenterPoint,
            firstSubLine.y1 + edge, //다음 선의 높이만큼 가져와서 edge길이를 합함
            vertCenterPoint,
            firstSubLine.y2 - edge, //다음 선의 높이만큼 가져옴 edge길이를 합함
          ],
          centerLineOpt,
        )
        canvas.add(vertCenterLine)
        outLines.push(vertCenterLine)

        //긴면 가로선 그리기
        let horiCenterPoint = (firstSubLine.y1 + firstSubLine.y2) / 2
        let horiCenterLine1 = new QLine(
          [firstLine.x1 - eaves, horiCenterPoint, firstLine.x1 - eaves + firstLine.length / 2 + eaves, horiCenterPoint],
          dashedCenterLineOpt,
        )

        canvas.add(horiCenterLine1)

        let horiCenterLine2 = new QLine(
          [
            firstLine.x1 - eaves + firstLine.length / 2 + eaves,
            horiCenterPoint,
            firstLine.x1 - eaves + firstLine.length / 2 + eaves + firstLine.length / 2 + eaves,
            horiCenterPoint,
          ],
          dashedCenterLineOpt,
        )
        canvas.add(horiCenterLine2)

        //작은 지붕쪽 높이 길이를 구하는 로직
        let secondVertCenterPoint = (lastLine.x1 + lastLine.x2) / 2
        secondVertCenterLine = new QLine([secondVertCenterPoint, middleSubLine.y1, secondVertCenterPoint, middleSubLine.y2 - edge], centerLineOpt)
        canvas.add(secondVertCenterLine)
        outLines.push(secondVertCenterLine)

        //작은 지붕쪽 너비 길이를 구한는 로직
        let secondHoriCenterLength = (Math.abs(lastLine.get('x1') - lastLine.get('x2')) + Math.abs(lastLine.get('y1') - lastLine.get('y2'))) / 2
        let secondHoriCenterPoint = (secondVertCenterLine.y1 + secondVertCenterLine.y2) / 2

        let secondHoriCenterLine = new QLine(
          [secondVertCenterLine.x1, secondHoriCenterPoint, secondVertCenterLine.x1 + secondHoriCenterLength + eaves, secondHoriCenterPoint],
          dashedCenterLineOpt,
        )
        canvas.add(secondHoriCenterLine)

        //일반라인 외각선 그리기
        normalIndexArray.forEach((index) => {
          const line = lines[index]
          let points = []
          if (index === 0) {
            points.push(line.x1 - eaves, line.y1 - edge, line.x2 - eaves, line.y2 + edge)
          } else {
            let tmpEdge = index === 2 ? edge : 0
            points.push(line.x1 + eaves, line.y1 + tmpEdge, line.x2 + eaves, line.y2 - edge)
          }
          let drawline = new QLine(points, centerLineOpt)
          canvas.add(drawline)
          outLines.push(drawline)
        })

        //케라바 라인 외각선 그리기
        const firstOuterLine = lines[1]
        const middleOuterLine = lines[3]
        const lastOuterLine = lines[5]

        //첫번째 외곽선 1번
        halfLength = firstOuterLine.length / 2
        let drawFirstLine1 = new QLine(
          [firstOuterLine.x1 - eaves, firstOuterLine.y1 + edge, firstOuterLine.x1 + halfLength, firstOuterLine.y2 + edge],
          centerLineOpt,
        )
        canvas.add(drawFirstLine1)
        outLines.push(drawFirstLine1)

        //첫번째 외곽선 2번
        let drawFirstLine2 = new QLine(
          [drawFirstLine1.x2, firstOuterLine.y1 + edge, firstOuterLine.x2 + eaves, firstOuterLine.y2 + edge],
          centerLineOpt,
        )
        canvas.add(drawFirstLine2)
        outLines.push(drawFirstLine2)

        //중간라인 외각선
        let drawMiddleLine = new QLine([drawFirstLine2.x2, middleOuterLine.y1 - edge, drawFirstLine2.x1, middleOuterLine.y2 - edge], centerLineOpt)
        canvas.add(drawMiddleLine)
        outLines.push(drawMiddleLine)

        //마지막 외각선
        halfLength = lastLine.length / 2
        let drawLastLine1 = new QLine(
          [lastOuterLine.x2 + halfLength, lastOuterLine.y1 - edge, lastOuterLine.x2 - eaves, lastOuterLine.y2 - edge],
          centerLineOpt,
        )
        canvas.add(drawLastLine1)
        outLines.push(drawLastLine1)

        let drawLastLine2 = new QLine(
          [drawLastLine1.x1, lastOuterLine.y1 - edge, lastOuterLine.x1 + length + eaves, lastOuterLine.y2 - edge],
          centerLineOpt,
        )
        canvas.add(drawLastLine2)
        outLines.push(drawLastLine2)

        let drawLastInLine1 = new QLine(
          [secondVertCenterLine.x1, secondVertCenterLine.y1, secondVertCenterLine.x1 + halfLength + eaves, secondVertCenterLine.y1],
          centerLineOpt,
        )
        canvas.add(drawLastInLine1)

        let drawLastInLine2 = new QLine([secondVertCenterLine.x1, vertCenterLine.y2, vertCenterLine.x2, vertCenterLine.y2], centerLineOpt)
        canvas.add(drawLastInLine2)

        bigRoofPolygon = [
          { x: outLines[2].x1, y: outLines[2].y1 },
          { x: outLines[2].x2, y: outLines[2].y2 },
          { x: outLines[0].x1, y: outLines[0].y1 },
          { x: outLines[0].x2, y: outLines[0].y2 },
          { x: outLines[1].x2, y: outLines[0].y2 },
          { x: outLines[1].x2, y: outLines[1].y2 },
        ]

        middleRoofPolygon = [
          { x: outLines[0].x2, y: outLines[0].y2 },
          { x: outLines[0].x1, y: outLines[0].y1 },
          { x: outLines[3].x2, y: outLines[3].y2 },
          { x: outLines[3].x1, y: outLines[3].y1 },
        ]

        smallRoofPolygon = [
          { x: outLines[1].x2, y: outLines[1].y2 },
          { x: outLines[1].x1, y: outLines[1].y1 },
          { x: outLines[4].x2, y: outLines[4].y2 },
          { x: outLines[4].x1, y: outLines[4].y1 },
        ]
      } else {
        //아래쪽 길게 오른쪽 방향
        //배열 순서대로 뒤에꺼를 찾아서 계산한다

        firstLine = lines[1]
        secondLine = lines[5]
        lastLine = lines[3]

        const firstSubLine = lines[0]
        const middleSubLine = lines[4]

        //ㄴ자 일경우
        //긴면 세로선 그리기
        let vertCenterPoint = (firstLine.x1 + firstLine.x2) / 2 //가장 긴선 중앙선 가운데 점
        vertCenterLine = new QLine(
          [
            vertCenterPoint,
            firstSubLine.y1 - edge, //다음 선의 높이만큼 가져와서 edge길이를 합함
            vertCenterPoint,
            firstSubLine.y2 + edge, //다음 선의 높이만큼 가져옴 edge길이를 합함
          ],
          centerLineOpt,
        )
        canvas.add(vertCenterLine)
        outLines.push(vertCenterLine)

        //긴면 가로선 그리기
        let horiCenterPoint = (firstSubLine.y1 + firstSubLine.y2) / 2
        let horiCenterLine1 = new QLine(
          [firstLine.x1 - eaves, horiCenterPoint, firstLine.x1 - eaves + firstLine.length / 2 + eaves, horiCenterPoint],
          dashedCenterLineOpt,
        )
        canvas.add(horiCenterLine1)

        let horiCenterLine2 = new QLine(
          [
            firstLine.x1 - eaves + firstLine.length / 2 + eaves,
            horiCenterPoint,
            firstLine.x1 - eaves + firstLine.length / 2 + eaves + firstLine.length / 2 + eaves,
            horiCenterPoint,
          ],
          dashedCenterLineOpt,
        )
        canvas.add(horiCenterLine2)

        //작은 지붕쪽 높이 길이를 구하는 로직
        let secondVertCenterPoint = (lastLine.x1 + lastLine.x2) / 2
        secondVertCenterLine = new QLine([secondVertCenterPoint, middleSubLine.y1 - edge, secondVertCenterPoint, middleSubLine.y2], centerLineOpt)
        canvas.add(secondVertCenterLine)
        outLines.push(secondVertCenterLine)

        //작은 지붕쪽 너비 길이를 구한는 로직
        let secondHoriCenterLength = (Math.abs(lastLine.get('x1') - lastLine.get('x2')) + Math.abs(lastLine.get('y1') - lastLine.get('y2'))) / 2
        let secondHoriCenterPoint = (secondVertCenterLine.y1 + secondVertCenterLine.y2) / 2

        let secondHoriCenterLine = new QLine(
          [secondVertCenterLine.x1 - secondHoriCenterLength - eaves, secondHoriCenterPoint, secondVertCenterLine.x1, secondHoriCenterPoint],
          dashedCenterLineOpt,
        )
        canvas.add(secondHoriCenterLine)

        //일반라인 외각선 그리기
        normalIndexArray.forEach((index) => {
          const line = lines[index]
          let points = []
          if (index === 0 || index === 4) {
            let tmpEdge = index === 4 ? 0 : edge
            points = [line.x1 - eaves, line.y1 - edge, line.x2 - eaves, line.y2 + tmpEdge]
          } else {
            points = [line.x1 + eaves, line.y1 + edge, line.x2 + eaves, line.y2 - edge]
          }
          let drawline = new QLine(points, centerLineOpt)
          canvas.add(drawline)
          outLines.push(drawline)
        })

        //케라바 라인 외각선 그리기
        const firstOuterLine = lines[1]
        const middleOuterLine = lines[5]
        const lastOuterLine = lines[3]

        //첫번째 외곽선 1번
        halfLength = firstOuterLine.length / 2
        let drawFirstLine1 = new QLine(
          [firstOuterLine.x1 - eaves, firstOuterLine.y1 + edge, firstOuterLine.x1 + halfLength, firstOuterLine.y2 + edge],
          centerLineOpt,
        )
        canvas.add(drawFirstLine1)
        outLines.push(drawFirstLine1)

        //첫번째 외곽선 2번
        let drawFirstLine2 = new QLine(
          [drawFirstLine1.x2, firstOuterLine.y1 + edge, firstOuterLine.x2 + eaves, firstOuterLine.y2 + edge],
          centerLineOpt,
        )
        canvas.add(drawFirstLine2)
        outLines.push(drawFirstLine2)

        //중간라인 외각선
        let drawMiddleLine = new QLine([drawFirstLine1.x1, middleOuterLine.y1 - edge, drawFirstLine1.x2, middleOuterLine.y2 - edge], centerLineOpt)
        canvas.add(drawMiddleLine)
        outLines.push(drawMiddleLine)

        //마지막 외각선
        halfLength = lastLine.length / 2

        let drawLastLine1 = new QLine(
          [lastOuterLine.x2 - eaves, lastOuterLine.y1 - edge, lastOuterLine.x1 - halfLength, lastOuterLine.y2 - edge],
          centerLineOpt,
        )
        canvas.add(drawLastLine1)

        let drawLastLine2 = new QLine(
          [drawLastLine1.x1, lastOuterLine.y1 - edge, lastOuterLine.x1 + length + eaves, lastOuterLine.y2 - edge],
          centerLineOpt,
        )
        canvas.add(drawLastLine2)

        let drawLastInLine1 = new QLine(
          [secondVertCenterLine.x1, secondVertCenterLine.y2, secondVertCenterLine.x1 - halfLength - eaves, secondVertCenterLine.y2],
          centerLineOpt,
        )
        canvas.add(drawLastInLine1)

        let drawLastInLine2 = new QLine([secondVertCenterLine.x2, vertCenterLine.y1, vertCenterLine.x1, vertCenterLine.y1], centerLineOpt)
        canvas.add(drawLastInLine2)

        bigRoofPolygon = [
          { x: outLines[0].x1, y: outLines[0].y1 },
          { x: outLines[0].x2, y: outLines[0].y2 },
          { x: outLines[3].x1, y: outLines[3].y1 },
          { x: outLines[3].x2, y: outLines[3].y2 },
          { x: outLines[1].x1, y: outLines[1].y1 },
          { x: outLines[1].x2, y: outLines[0].y1 },
        ]

        middleRoofPolygon = [
          { x: outLines[2].x1, y: outLines[2].y1 },
          { x: outLines[2].x2, y: outLines[2].y2 },
          { x: outLines[0].x2, y: outLines[0].y2 },
          { x: outLines[0].x1, y: outLines[0].y1 },
        ]

        smallRoofPolygon = [
          { x: outLines[4].x1, y: outLines[4].y1 },
          { x: outLines[4].x2, y: outLines[4].y2 },
          { x: outLines[1].x2, y: outLines[1].y2 },
          { x: outLines[1].x1, y: outLines[1].y1 },
        ]
      }
    } else {
      if (horizontalDirection === 'left') {
        //아래쪽 길게 오른쪽 방향
        //배열 순서대로 뒤에꺼를 찾아서 계산한다
        firstLine = lines[5]
        secondLine = lines[3]
        lastLine = lines[1]

        const firstSubLine = lines[4]
        const middleSubLine = lines[2]

        //ㄴ자 일경우
        //긴면 세로선 그리기
        let vertCenterPoint = (firstLine.x1 + firstLine.x2) / 2 //가장 긴선 중앙선 가운데 점
        vertCenterLine = new QLine(
          [
            vertCenterPoint,
            firstSubLine.y2 - edge, //다음 선의 높이만큼 가져와서 edge길이를 합함
            vertCenterPoint,
            firstSubLine.y1 + edge, //다음 선의 높이만큼 가져옴 edge길이를 합함
          ],
          centerLineOpt,
        )
        canvas.add(vertCenterLine)
        outLines.push(vertCenterLine)

        //긴면 가로선 그리기
        let horiCenterPoint = (firstSubLine.y1 + firstSubLine.y2) / 2
        let horiCenterLine1 = new QLine(
          [firstLine.x2 - eaves, horiCenterPoint, firstLine.x2 - eaves + firstLine.length / 2 + eaves, horiCenterPoint],
          dashedCenterLineOpt,
        )
        canvas.add(horiCenterLine1)

        let horiCenterLine2 = new QLine(
          [
            firstLine.x2 - eaves + firstLine.length / 2 + eaves,
            horiCenterPoint,
            firstLine.x2 - eaves + firstLine.length / 2 + eaves + firstLine.length / 2 + eaves,
            horiCenterPoint,
          ],
          dashedCenterLineOpt,
        )
        canvas.add(horiCenterLine2)

        //작은 지붕쪽 높이 길이를 구하는 로직
        let secondVertCenterPoint = (lastLine.x1 + lastLine.x2) / 2
        secondVertCenterLine = new QLine([secondVertCenterPoint, middleSubLine.y1 + edge, secondVertCenterPoint, middleSubLine.y2], centerLineOpt)
        canvas.add(secondVertCenterLine)
        outLines.push(secondVertCenterLine)

        //작은 지붕쪽 너비 길이를 구한는 로직
        let secondHoriCenterLength = (Math.abs(lastLine.get('x1') - lastLine.get('x2')) + Math.abs(lastLine.get('y1') - lastLine.get('y2'))) / 2
        let secondHoriCenterPoint = (secondVertCenterLine.y1 + secondVertCenterLine.y2) / 2
        let secondHoriCenterLine = new QLine(
          [secondVertCenterLine.x1 + secondHoriCenterLength + eaves, secondHoriCenterPoint, secondVertCenterLine.x1, secondHoriCenterPoint],
          dashedCenterLineOpt,
        )
        canvas.add(secondHoriCenterLine)

        //일반라인 외각선 그리기
        normalIndexArray.forEach((index) => {
          const line = lines[index]
          let points = []
          if (index === 0) {
            points = [line.x1 - eaves, line.y1 - edge, line.x2 - eaves, line.y2 + edge]
          } else {
            let tmpEdge = index === 2 ? 0 : edge
            points = [line.x1 + eaves, line.y1 + edge, line.x2 + eaves, line.y2 - tmpEdge]
          }

          let drawline = new QLine(points, centerLineOpt)
          canvas.add(drawline)
          outLines.push(drawline)
        })

        //케라바 라인 외각선 그리기
        const firstOuterLine = lines[5]
        const middleOuterLine = lines[3]
        const lastOuterLine = lines[1]

        //첫번째 외곽선 1번
        halfLength = firstOuterLine.length / 2
        let drawFirstLine1 = new QLine(
          [firstOuterLine.x2 - eaves, firstOuterLine.y1 - edge, firstOuterLine.x2 + halfLength, firstOuterLine.y2 - edge],
          centerLineOpt,
        )
        canvas.add(drawFirstLine1)

        //첫번째 외곽선 2번
        let drawFirstLine2 = new QLine(
          [drawFirstLine1.x2, drawFirstLine1.y1, drawFirstLine1.x2 + halfLength + eaves, drawFirstLine1.y2],
          centerLineOpt,
        )
        canvas.add(drawFirstLine2)

        //중간라인 외각선
        let drawMiddleLine = new QLine([drawFirstLine2.x1, middleOuterLine.y1 + edge, drawFirstLine2.x2, middleOuterLine.y2 + edge], centerLineOpt)
        canvas.add(drawMiddleLine)

        //마지막 외각선
        halfLength = lastLine.length / 2
        let drawLastLine1 = new QLine(
          [lastOuterLine.x1 - eaves, lastOuterLine.y1 + edge, lastOuterLine.x1 + halfLength, lastOuterLine.y2 + edge],
          centerLineOpt,
        )
        canvas.add(drawLastLine1)

        let drawLastLine2 = new QLine([drawLastLine1.x2, drawLastLine1.y1, drawLastLine1.x2 + halfLength + eaves, drawLastLine1.y1], centerLineOpt)
        canvas.add(drawLastLine2)

        let drawLastInLine1 = new QLine(
          [secondVertCenterLine.x1, secondVertCenterLine.y2, secondVertCenterLine.x1 + halfLength + eaves, secondVertCenterLine.y2],
          centerLineOpt,
        )
        canvas.add(drawLastInLine1)

        let drawLastInLine2 = new QLine([vertCenterLine.x1, vertCenterLine.y2, secondVertCenterLine.x2, vertCenterLine.y2], centerLineOpt)
        canvas.add(drawLastInLine2)

        bigRoofPolygon = [
          { x: outLines[2].x1, y: outLines[2].y1 },
          { x: outLines[2].x2, y: outLines[2].y2 },
          { x: outLines[1].x1, y: outLines[1].y1 },
          { x: outLines[1].x2, y: outLines[0].y2 },
          { x: outLines[0].x1, y: outLines[0].y2 },
          { x: outLines[0].x1, y: outLines[0].y1 },
        ]

        middleRoofPolygon = [
          { x: outLines[0].x1, y: outLines[0].y1 },
          { x: outLines[0].x2, y: outLines[0].y2 },
          { x: outLines[4].x2, y: outLines[4].y2 },
          { x: outLines[4].x1, y: outLines[4].y1 },
        ]

        smallRoofPolygon = [
          { x: outLines[1].x2, y: outLines[1].y2 },
          { x: outLines[1].x1, y: outLines[1].y1 },
          { x: outLines[3].x2, y: outLines[3].y2 },
          { x: outLines[3].x1, y: outLines[3].y1 },
        ]
      } else {
        //윗쪽 길게 오른쪽 방향
        //배열 순서대로 뒤에꺼를 찾아서 계산한다
        firstLine = lines[5]
        secondLine = lines[1]
        lastLine = lines[3]

        const firstSubLine = lines[0]
        const middleSubLine = lines[2]

        //ㄴ자 일경우
        //긴면 세로선 그리기
        let vertCenterPoint = (firstLine.x1 + firstLine.x2) / 2 //가장 긴선 중앙선 가운데 점
        vertCenterLine = new QLine(
          [
            vertCenterPoint,
            firstSubLine.y1 - edge, //다음 선의 높이만큼 가져와서 edge길이를 합함
            vertCenterPoint,
            firstSubLine.y2 + edge, //다음 선의 높이만큼 가져옴 edge길이를 합함
          ],
          centerLineOpt,
        )
        canvas.add(vertCenterLine)
        outLines.push(vertCenterLine)

        //긴면 가로선 그리기
        let horiCenterPoint = (firstSubLine.y1 + firstSubLine.y2) / 2
        let horiCenterLine1 = new QLine(
          [firstLine.x2 - eaves, horiCenterPoint, firstLine.x2 - eaves + firstLine.length / 2 + eaves, horiCenterPoint],
          dashedCenterLineOpt,
        )
        canvas.add(horiCenterLine1)

        let horiCenterLine2 = new QLine(
          [
            firstLine.x2 - eaves + firstLine.length / 2 + eaves,
            horiCenterPoint,
            firstLine.x2 - eaves + firstLine.length / 2 + eaves + firstLine.length / 2 + eaves,
            horiCenterPoint,
          ],
          dashedCenterLineOpt,
        )
        canvas.add(horiCenterLine2)

        //작은 지붕쪽 높이 길이를 구하는 로직
        let secondVertCenterPoint = (lastLine.x1 + lastLine.x2) / 2
        secondVertCenterLine = new QLine([secondVertCenterPoint, middleSubLine.y1, secondVertCenterPoint, middleSubLine.y2 + edge], {
          stroke: 'blue',
          strokeWidth: 4,
          property: 'centerLine',
          fontSize: 14,
        })

        canvas.add(secondVertCenterLine)
        outLines.push(secondVertCenterLine)
        //작은 지붕쪽 너비 길이를 구한는 로직
        let secondHoriCenterLength = (Math.abs(lastLine.get('x1') - lastLine.get('x2')) + Math.abs(lastLine.get('y1') - lastLine.get('y2'))) / 2
        let secondHoriCenterPoint = (secondVertCenterLine.y1 + secondVertCenterLine.y2) / 2

        let secondHoriCenterLine = new QLine(
          [secondVertCenterLine.x1, secondHoriCenterPoint, secondVertCenterLine.x1 - secondHoriCenterLength - eaves, secondHoriCenterPoint],
          dashedCenterLineOpt,
        )
        canvas.add(secondHoriCenterLine)

        //일반라인 외각선 그리기
        normalIndexArray.forEach((index) => {
          const line = lines[index]
          let drawline
          if (index === 0 || index === 2) {
            let tmpEdge = index === 2 ? 0 : edge
            drawline = new QLine([line.x1 - eaves, line.y1 - tmpEdge, line.x2 - eaves, line.y2 + edge], centerLineOpt)
            canvas.add(drawline)
          } else {
            drawline = new QLine([line.x1 + eaves, line.y1 + edge, line.x2 + eaves, line.y2 - edge], centerLineOpt)
            canvas.add(drawline)
          }
          outLines.push(drawline)
        })

        //케라바 라인 외각선 그리기
        const firstOuterLine = lines[5]
        const middleOuterLine = lines[1]
        const lastOuterLine = lines[3]

        //첫번째 외곽선 1번
        halfLength = firstOuterLine.length / 2
        let drawFirstLine1 = new QLine(
          [firstOuterLine.x2 - eaves, firstOuterLine.y1 - edge, firstOuterLine.x2 + halfLength, firstOuterLine.y2 - edge],
          centerLineOpt,
        )
        canvas.add(drawFirstLine1)

        //첫번째 외곽선 2번
        let drawFirstLine2 = new QLine(
          [drawFirstLine1.x2, drawFirstLine1.y1, drawFirstLine1.x2 + halfLength + eaves, drawFirstLine1.y2],
          centerLineOpt,
        )
        canvas.add(drawFirstLine2)

        //중간라인 외각선
        let drawMiddleLine = new QLine([drawFirstLine1.x1, middleOuterLine.y1 + edge, drawFirstLine1.x2, middleOuterLine.y2 + edge], centerLineOpt)
        canvas.add(drawMiddleLine)

        //마지막 외각선
        halfLength = lastLine.length / 2
        let drawLastLine1 = new QLine(
          [lastOuterLine.x1 - eaves, lastOuterLine.y1 + edge, lastOuterLine.x1 + halfLength, lastOuterLine.y2 + edge],
          centerLineOpt,
        )
        canvas.add(drawLastLine1)

        let drawLastLine2 = new QLine([drawLastLine1.x2, drawLastLine1.y1, drawLastLine1.x2 + halfLength + eaves, drawLastLine1.y1], centerLineOpt)
        canvas.add(drawLastLine2)

        let drawLastInLine1 = new QLine([vertCenterLine.x2, vertCenterLine.y2, secondVertCenterLine.x1, vertCenterLine.y2], centerLineOpt)
        canvas.add(drawLastInLine1)

        let drawLastInLine2 = new QLine([secondLine.x2 - eaves, secondLine.y1, drawLastLine1.x2, secondLine.y1], centerLineOpt)
        canvas.add(drawLastInLine2)

        bigRoofPolygon = [
          { x: outLines[0].x1, y: outLines[0].y1 },
          { x: outLines[0].x2, y: outLines[0].y2 },
          { x: outLines[1].x1, y: outLines[0].y2 },
          { x: outLines[1].x2, y: outLines[1].y2 },
          { x: outLines[4].x1, y: outLines[4].y1 },
          { x: outLines[4].x2, y: outLines[4].y2 },
        ]

        middleRoofPolygon = [
          { x: outLines[2].x1, y: outLines[2].y1 },
          { x: outLines[2].x2, y: outLines[2].y2 },
          { x: outLines[0].x2, y: outLines[0].y2 },
          { x: outLines[0].x1, y: outLines[0].y1 },
        ]

        smallRoofPolygon = [
          { x: outLines[3].x1, y: outLines[3].y1 },
          { x: outLines[3].x2, y: outLines[3].y2 },
          { x: outLines[1].x2, y: outLines[1].y2 },
          { x: outLines[1].x1, y: outLines[1].y1 },
        ]
      }
    }

    roofPatternPolygonArray.push(bigRoofPolygon) //지붕폴리곤
    roofPatternPolygonArray.push(middleRoofPolygon) //중간라인 폴리곤
    roofPatternPolygonArray.push(smallRoofPolygon) //작은지붕폴리곤
    setRoofPolygonPattern({ roofPatternPolygonArray, lines }) //모든 행을 저장

    canvas?.renderAll()
  }

  const handleOuterLineTemplateA8Points = (polygon, offsetInputX = 20, offsetInputY = 50) => {
    let offsetPoints = []

    const originalMax = 71
    const transformedMax = 100

    let lines = [] //내각라인
    let outLines = [] //아웃라인
    let halfLength = 0 //선길이
    let offsetX
    let offsetY

    const dashedCenterLineOpt = {
      stroke: 'black',
      strokeWidth: 1,
      property: 'centerLine',
      strokeDashArray: [8, 4],
      fontSize: 14,
    }

    const centerLineOpt = {
      stroke: 'blue',
      strokeWidth: 2,
      property: 'bigHoriCenter',
      fontSize: 14,
    }

    // 폴리곤의 각 변을 선으로 생성
    for (let i = 0; i < polygon.points.length; i++) {
      const start = polygon.points[i]
      const end = polygon.points[(i + 1) % polygon.points.length] // 다음 점, 마지막 점의 경우 첫 점으로

      const line = new QLine([start.x, start.y, end.x, end.y], {
        stroke: '#A0D468',
        strokeWidth: 2,
        property: 'normal',
        fontSize: 14,
      })

      // 선을 배열에 추가
      lines.push(line)
      canvas.add(line)
    }

    offsetInputY = offsetInputY !== 0 ? offsetInputY : offsetInputX

    const sortedIndex = getStartIndex(polygon.lines)
    let tmpArraySorted = rearrangeArray(polygon.lines, sortedIndex)
    setSortedArray(tmpArraySorted) //recoil에 넣음

    const points = tmpArraySorted.map((line) => ({
      x: line.x1,
      y: line.y1,
    }))

    //좌표 재정렬
    function reSortQlineArray(array) {
      let tmpArray = []
      let minX, minY, maxX, maxY
      let tmp
      array.forEach((arr, index) => {
        tmp = arr
        if (arr.x2 < arr.x1 || arr.y2 < arr.y1) {
          minX = arr.x2
          minY = arr.y2
          maxX = arr.x1
          maxY = arr.y1
          tmp['x1'] = minX
          tmp['y1'] = minY
          tmp['x2'] = maxX
          tmp['y2'] = maxY
          tmp.line['x1'] = minX
          tmp.line['y1'] = minY
          tmp.line['x2'] = maxX
          tmp.line['y2'] = maxY
        }
        tmpArray.push(tmp)
      })

      return tmpArray
    }

    // 외적을 계산하는 함수
    function crossProduct(p1, p2, p3) {
      const dx1 = p2.x - p1.x
      const dy1 = p2.y - p1.y
      const dx2 = p3.x - p2.x
      const dy2 = p3.y - p2.y
      return dx1 * dy2 - dy1 * dx2
    }

    let concaveIndices = [] //볼록한 부분 인덱스 배열
    let concavePointIndices = [] //오목한 부분 인덱스 배열

    // 오목한 부분 찾기
    function findConcavePointIndices(points) {
      let concaveIndices = []
      for (let i = 0; i < points.length; i++) {
        const p1 = points[i]
        const p2 = points[(i + 1) % points.length]
        const p3 = points[(i + 2) % points.length]
        const cross = crossProduct(p1, p2, p3)
        if (cross < 0) {
          concaveIndices.push((i + 1) % points.length)
        } else {
          concavePointIndices.push((i + 1) % points.length)
        }
      }
      return concaveIndices
    }

    // 오목한 부분 인덱스 찾기
    concaveIndices = findConcavePointIndices(points) //오목한 부분을 제외한 인덱스
    const concavePoints = concaveIndices.map((index) => points[index])
    const concaveLine = {
      index: concavePointIndices[0],
      line: lines[concavePointIndices[0]],
    }

    for (let i = 0; i < points.length; i++) {
      let prev = points[(i - 1 + points.length) % points.length]
      let current = points[i]
      let next = points[(i + 1) % points.length]

      // 두 벡터 계산 (prev -> current, current -> next)
      let vector1 = { x: current.x - prev.x, y: current.y - prev.y }
      let vector2 = { x: next.x - current.x, y: next.y - current.y }

      // 벡터의 길이 계산
      let length1 = Math.sqrt(vector1.x * vector1.x + vector1.y * vector1.y)
      let length2 = Math.sqrt(vector2.x * vector2.x + vector2.y * vector2.y)

      // 벡터를 단위 벡터로 정규화
      let unitVector1 = { x: vector1.x / length1, y: vector1.y / length1 }
      let unitVector2 = { x: vector2.x / length2, y: vector2.y / length2 }

      // 법선 벡터 계산 (왼쪽 방향)
      let normal1 = { x: -unitVector1.y, y: unitVector1.x }
      let normal2 = { x: -unitVector2.y, y: unitVector2.x }

      // 법선 벡터 평균 계산
      let averageNormal = {
        x: (normal1.x + normal2.x) / 2,
        y: (normal1.y + normal2.y) / 2,
      }

      // 평균 법선 벡터를 단위 벡터로 정규화
      let lengthNormal = Math.sqrt(averageNormal.x * averageNormal.x + averageNormal.y * averageNormal.y)
      let unitNormal = {
        x: averageNormal.x / lengthNormal,
        y: averageNormal.y / lengthNormal,
      }

      offsetX = (offsetInputX / transformedMax) * originalMax * 2
      offsetY = (offsetInputY / transformedMax) * originalMax * 2

      // 오프셋 적용
      let offsetPoint = {
        x1: current.x + unitNormal.x * offsetX,
        y1: current.y + unitNormal.y * offsetY,
      }

      offsetPoints.push(offsetPoint)
    }

    const outlinePolygon = makePolygon(offsetPoints)
    outlinePolygon.setViewLengthText(false)

    // 아웃라인 폴리곤의 각 변을 선으로 생성
    for (let i = 0; i < outlinePolygon.points.length; i++) {
      const start = outlinePolygon.points[i]
      const end = outlinePolygon.points[(i + 1) % outlinePolygon.points.length] // 다음 점, 마지막 점의 경우 첫 점으로

      const line = new QLine([start.x, start.y, end.x, end.y], {
        stroke: 'blue',
        strokeWidth: 2,
        property: 'normal',
        fontSize: 14,
        idx: i,
      })

      // 선을 배열에 추가
      outLines.push(line)
      canvas.add(line)
    }

    canvas?.remove(outlinePolygon) //임시 폴리곤을 삭제

    let parallelLinesIdx = concavePointIndices[0] + 4 //들어간선에 무조건 평행하는 선 찾기
    if (parallelLinesIdx >= outLines.length) {
      parallelLinesIdx = parallelLinesIdx - outLines.length
    }

    let vertCenterLine = []
    let halfHoriCenterLinePoint = [] //카라바선의 2분할의 1번 배열
    let horiCenterLine = []
    let shorVertCenterLine = []

    let edgeIndexArray = []

    if (concavePointIndices[0] % 2 === 0) {
      //concave가 짝수면 좌우로 그려진 ㄷ자
      //케라바 색을 바꾼다
      lines.forEach((line, index) => {
        if (index % 2 === 0) {
          line.line.set('stroke', 'skyblue')
          if (concavePointIndices[0] !== index) {
            edgeIndexArray.push(index)
          }
        }
      })

      outLines = reSortQlineArray(outLines)
      edgeIndexArray.forEach((idx, index) => {
        //가로라인이 케라바 라인임
        if (concavePointIndices[0] !== idx) {
          //오목이가 아니면 반으로 갈라서 계산

          //카라바 선의 2분할 치수를 그림
          let halfLength = outLines[idx].length / 2
          let centerLine1 = new QLine([outLines[idx].x1, outLines[idx].y1, outLines[idx].x1, outLines[idx].y1 + halfLength], centerLineOpt)
          canvas.add(centerLine1)

          let centerLine2 = new QLine([outLines[idx].x1, centerLine1.y2, outLines[idx].x2, centerLine1.y2 + halfLength], centerLineOpt)
          canvas.add(centerLine2)
          canvas.remove(outLines[idx]) //기존 라인 삭제

          halfHoriCenterLinePoint.push({
            index: idx,
            x1: centerLine1.x1,
            y1: centerLine1.y1,
            x2: centerLine1.x2,
            y2: centerLine1.y2,
          }) //각 카라바 라인의 1번이 마지막점을 잡아서 센터선으로 설정
        }
      })

      // //각 센터 라인을 그림
      halfHoriCenterLinePoint.forEach((centerPoint) => {
        let tmpX2 = parallelLinesIdx !== centerPoint.index ? concaveLine.line.x2 : outLines[concavePointIndices[0]].x1 //평행선에서 내려오는 선은 아웃라인에 닿아야한다

        let line = new QLine([centerPoint.x2, centerPoint.y2, tmpX2, centerPoint.y2], centerLineOpt)
        canvas.add(line)

        line['arrayIndex'] = centerPoint.index //커스텀으로 기존 index를 넣어줌
        vertCenterLine.push(line)
      })

      vertCenterLine = reSortQlineArray(vertCenterLine)
      lines = reSortQlineArray(lines)

      //해당라인에서 만나는점을 계산
      vertCenterLine.forEach((vertLine) => {
        if (parallelLinesIdx !== vertLine.arrayIndex) {
          //평행선을 제외한 애들만 네모를 연결
          let nearLine
          let nearOutline
          if (vertLine.arrayIndex > concaveLine.index) {
            //센터에 인덱스가 오목점 보다 크면 다음 작으면 앞에꺼
            nearLine = lines[concaveLine.index + 1]
            nearOutline = outLines[concaveLine.index + 1]
          } else {
            nearLine = lines[concaveLine.index - 1]
            nearOutline = outLines[concaveLine.index - 1]
          }

          let nearLineY = nearLine.y1
          if (parallelLinesIdx < concaveLine.index) {
            //오목점 위치가 평행선보다 크면 위쪽으로 오목
            nearLineY = nearLine.y2
          }

          //기존에 있는 라인에서 연장해서 새로 그림
          let centerExtendHoriLine = new QLine([vertLine.x1, nearOutline.line.y1, vertLine.x2, nearOutline.line.y2], centerLineOpt)
          canvas.add(centerExtendHoriLine)
          canvas.remove(nearOutline)
          outLines.splice(nearOutline.idx, 1, centerExtendHoriLine) //아웃라인에 데이터를 다시 넣는다

          //가로형에선 기본으로 ㄷ자 형태로 한다
          let centerExtendLine = new QLine([vertLine.line.x1, vertLine.line.y1, centerExtendHoriLine.x1, centerExtendHoriLine.y1], centerLineOpt)

          //오목이가 배열에 반보다 작으면 역 ㄷ자 여서 변경
          if (concavePointIndices[0] < outLines.length / 2) {
            centerExtendLine = new QLine([vertLine.line.x2, vertLine.line.y2, centerExtendHoriLine.x2, centerExtendHoriLine.y2], centerLineOpt)
          }

          canvas.add(centerExtendLine) //새로그리고

          let betweenCenterLine = (vertLine.line.x1 + vertLine.line.x2) / 2
          let centerDashLine = new QLine([betweenCenterLine, centerExtendLine.y1, betweenCenterLine, centerExtendLine.y2], dashedCenterLineOpt)

          canvas.add(centerDashLine)
          horiCenterLine.push(centerDashLine)
          shorVertCenterLine.push(vertLine) //마지막에 가운데 선을 긋기 위해 담음
        } else {
          let longDashLine = halfHoriCenterLinePoint.find((obj) => obj.index === parallelLinesIdx) //평행선

          let dashCenterExtendLineLength = longDashLine.y2 - longDashLine.y1 //y반개 길이
          let betweenCenterLine = (vertLine.line.x1 + vertLine.line.x2) / 2 //y의 길이
          let totalLength = ((longDashLine.y2 - longDashLine.y1) * 2) / dashCenterExtendLineLength //2개로 나눔

          //반 쪼개서 그린다
          for (let i = 0; i < totalLength; i++) {
            //2번에 나눠서
            let startY = i === 0 ? longDashLine.y1 : longDashLine.y1 + dashCenterExtendLineLength //시작 하는 y의 좌표
            //x값은 고정이임 //TODO: 지붕 각도 계산법에 의해 재계산해야함
            let centerDashLine = new QLine([betweenCenterLine, startY, betweenCenterLine, startY + dashCenterExtendLineLength], dashedCenterLineOpt)
            canvas.add(centerDashLine)
            horiCenterLine.push(centerDashLine)
          }
        }
      })

      //마지막에 오목한 외곽선을 연장한다
      const tmpLastOutLine = outLines[concavePointIndices[0]]
      const lastOutLine = new QLine([tmpLastOutLine.x1, shorVertCenterLine[0].y1, tmpLastOutLine.x1, shorVertCenterLine[1].y1], centerLineOpt)
      canvas.add(lastOutLine)
      canvas.remove(tmpLastOutLine)

      //폴리곤 패턴을 그리기 위해 작성
      let tmpVertCenterLine = outLines.filter((x, index) => index % 2 !== 0) //세로만 찾음
      tmpVertCenterLine = tmpVertCenterLine.concat(vertCenterLine)
      tmpVertCenterLine.sort((a, b) => a.y1 - b.y1)
      tmpVertCenterLine.push(lastOutLine)

      let roofPatternPolygonArray = []
      let tmpArray = []
      let tmpBigArray = []

      console.log('tmpVertCenterLine', tmpVertCenterLine)

      const lastCenterLine = tmpVertCenterLine[tmpVertCenterLine.length - 1] //마지막 센터라인을 정의

      for (let i = 0; i < tmpVertCenterLine.length - 1; i++) {
        //-1인건 마지막은 오목한 선이라 돌 필요 없음
        //라인 하나에 두점씩 나온다
        let firstPointObj = {}
        let secondPointObj = {}

        let x1 = tmpVertCenterLine[i].x1
        let y1 = tmpVertCenterLine[i].y1
        let x2 = tmpVertCenterLine[i].x2
        let y2 = tmpVertCenterLine[i].y2

        if (i === 2 || i === 4) {
          //작은 네모들
          tmpArray = []
          const prevLine = tmpVertCenterLine[i - 1] //뒤에서 앞라인을 찾는다
          const nextLine = tmpVertCenterLine[i + 1]

          //내 앞뒤 라인
          const tmpX1 = i === 2 ? prevLine.x1 : nextLine.x1
          const tmpY1 = i === 2 ? prevLine.y1 : nextLine.y1
          const tmpX2 = i === 2 ? prevLine.x2 : nextLine.x2
          const tmpY2 = i === 2 ? prevLine.y2 : nextLine.y2

          firstPointObj = { x: tmpX1, y: tmpY1 }
          secondPointObj = { x: tmpX2, y: tmpY2 }
          tmpArray.push(firstPointObj)
          tmpArray.push(secondPointObj)

          //현재 내 선
          firstPointObj = { x: x1, y: y1 }
          secondPointObj = { x: x2, y: y2 }
          tmpArray.push(firstPointObj)
          tmpArray.push(secondPointObj)
          roofPatternPolygonArray.push(tmpArray)
        } else {
          //큰 육각
          if (i === 1 || i === 5) {
            // 큰 폴리곤은 가운데 선으로 되야됨
            if (outLines.length / 2 > concavePointIndices[0]) {
              x2 = i === 1 ? lastCenterLine.x1 : lastCenterLine.x2
              y2 = i === 1 ? lastCenterLine.y1 : lastCenterLine.y2
            } else {
              //오목이가 배열 전체보다 크면 오른쪽 오목이
              x1 = i === 1 ? lastCenterLine.x1 : lastCenterLine.x2
              y1 = i === 1 ? lastCenterLine.y2 : lastCenterLine.y1
            }
          }

          if (i === 5) {
            //5번일때는 앞에 3번에 선이 필요하다
            let prevX1 = tmpVertCenterLine[i - 2].x1
            let prevY1 = tmpVertCenterLine[i - 2].y1
            let prevX2 = tmpVertCenterLine[i - 2].x2
            let prevY2 = tmpVertCenterLine[i - 2].y2
            firstPointObj = { x: prevX1, y: prevY1 }
            secondPointObj = { x: prevX2, y: prevY2 }
            tmpBigArray.push(firstPointObj)
            tmpBigArray.push(secondPointObj)
          }

          firstPointObj = { x: x1, y: y1 }
          secondPointObj = { x: x2, y: y2 }
          tmpBigArray.push(firstPointObj)
          tmpBigArray.push(secondPointObj)

          if (i === 3 || i === 6) {
            roofPatternPolygonArray.push(tmpBigArray)
            tmpBigArray = []
          }
        }
      }

      console.log('roofPatternPolygonArray', roofPatternPolygonArray)

      setRoofPolygonPattern({ roofPatternPolygonArray, lines })
    } else {
      // 오목한 부분이 세로선일때 아래ㄷ, 위ㄷ
      //라인들을 좌측에서 -> 우측으로 그리는거처럼 데이터 보정

      lines.forEach((line, index) => {
        if (!(index % 2 === 0)) {
          line.line.set('stroke', 'skyblue')
        }
      })
      outLines = reSortQlineArray(outLines)
      outLines.forEach((outline, index) => {
        if (!(index % 2 === 0)) {
          //세로라인이 케라바 라인임

          if (concavePointIndices[0] !== index) {
            //오목이가 아니면 반으로 갈라서 계산

            //카라바 선의 2분할 치수를 그림
            let halfLength = outline.length / 2
            let centerLine1 = new QLine([outline.x1, outline.y1, outline.x1 + halfLength, outline.y1], centerLineOpt)
            canvas.add(centerLine1)

            let centerLine2 = new QLine([centerLine1.x2, outline.y1, centerLine1.x2 + halfLength, outline.y1], centerLineOpt)
            canvas.add(centerLine2)
            canvas.remove(outline) //기존 라인 삭제

            halfHoriCenterLinePoint.push({
              index: index,
              x1: centerLine1.x1,
              y1: centerLine1.y1,
              x2: centerLine1.x2,
              y2: centerLine1.y2,
            }) //각 카라바 라인의 1번이 마지막점을 잡아서 센터선으로 설정
          }
        }
      })

      //각 센터 라인을 그림
      halfHoriCenterLinePoint.forEach((centerPoint) => {
        let tmpY2 = parallelLinesIdx !== centerPoint.index ? concaveLine.line.y1 : outLines[concavePointIndices[0]].y2 //평행선에서 내려오는 선은 아웃라인에 닿아야한다

        let line = new QLine([centerPoint.x2, centerPoint.y1, centerPoint.x2, tmpY2], centerLineOpt)
        canvas.add(line)

        line['arrayIndex'] = centerPoint.index //커스텀으로 기존 index를 넣어줌
        vertCenterLine.push(line)
      })

      vertCenterLine = reSortQlineArray(vertCenterLine)
      lines = reSortQlineArray(lines)

      //해당라인에서 만나는점을 계산
      vertCenterLine.forEach((vertLine) => {
        if (parallelLinesIdx !== vertLine.arrayIndex) {
          //평행선을 제외한 애들만 네모를 연결
          let nearLine
          let nearOutline
          if (vertLine.arrayIndex > concaveLine.index) {
            //센터에 인덱스가 오목점 보다 크면 다음 작으면 앞에꺼
            nearLine = lines[concaveLine.index + 1]
            nearOutline = outLines[concaveLine.index + 1]
          } else {
            nearLine = lines[concaveLine.index - 1]
            nearOutline = outLines[concaveLine.index - 1]
          }

          let nearLineY = nearLine.y1
          if (parallelLinesIdx < concaveLine.index) {
            //오목점 위치가 평행선보다 크면 위쪽으로 오목
            nearLineY = nearLine.y2
          }

          let centerExtendLine = new QLine([vertLine.line.x1, nearLineY, nearOutline.x1, nearLineY], centerLineOpt)
          canvas.add(centerExtendLine) //새로그리고

          //기존에 있는 라인에서 연장해서 새로 그림
          let centerExtendHoriLine = new QLine([nearOutline.line.x1, vertLine.y1, nearOutline.line.x2, vertLine.line.y2], centerLineOpt)
          canvas.add(centerExtendHoriLine)
          canvas.remove(nearOutline)
          outLines.splice(nearOutline.idx, 1, centerExtendHoriLine) //아웃라인에 데이터를 다시 넣는다

          let betweenCenterLine = (vertLine.line.y1 + vertLine.line.y2) / 2
          let centerDashLine = new QLine([vertLine.line.x1, betweenCenterLine, nearOutline.x1, betweenCenterLine], dashedCenterLineOpt)

          canvas.add(centerDashLine)
          horiCenterLine.push(centerDashLine)
          shorVertCenterLine.push(vertLine) //마지막에 가운데 선을 긋기 위해 담음
        } else {
          let longDashLine = halfHoriCenterLinePoint.find((obj) => obj.index === parallelLinesIdx)

          let dashCenterExtendLineLength = longDashLine.x2 - longDashLine.x1
          let betweenCenterLine = (vertLine.line.y1 + vertLine.line.y2) / 2
          let totalLength = ((longDashLine.x2 - longDashLine.x1) * 2) / dashCenterExtendLineLength

          //반 쪼개서 그린다
          for (let i = 0; i < totalLength; i++) {
            let startX = i === 0 ? longDashLine.x1 : longDashLine.x1 + dashCenterExtendLineLength
            let centerDashLine = new QLine([startX, betweenCenterLine, startX + dashCenterExtendLineLength, betweenCenterLine], dashedCenterLineOpt)
            canvas.add(centerDashLine)
            horiCenterLine.push(centerDashLine)
          }
        }
      })

      //마지막에 오목한 외곽선을 연장한다
      const tmpLastOutLine = outLines[concavePointIndices[0]]
      const lastOutLine = new QLine([shorVertCenterLine[0].x1, tmpLastOutLine.y1, shorVertCenterLine[1].x1, tmpLastOutLine.y2], centerLineOpt)
      canvas.add(lastOutLine)
      canvas.remove(tmpLastOutLine)

      let tmpVertCenterLine = outLines.filter((x, index) => index % 2 === 0) //세로만 찾음
      tmpVertCenterLine = tmpVertCenterLine.concat(vertCenterLine)
      tmpVertCenterLine.sort((a, b) => a.x1 - b.x1)
      tmpVertCenterLine.push(lastOutLine)

      let roofPatternPolygonArray = []
      let tmpArray = []
      let tmpBigArray = []

      const lastCenterLine = tmpVertCenterLine[tmpVertCenterLine.length - 1] //마지막 센터라인을 정의

      for (let i = 0; i < tmpVertCenterLine.length - 1; i++) {
        //-1인건 마지막은 오목한 선이라 돌 필요 없음
        //라인 하나에 두점씩 나온다
        let firstPointObj = {}
        let secondPointObj = {}

        let x1 = tmpVertCenterLine[i].x1
        let y1 = tmpVertCenterLine[i].y1
        let x2 = tmpVertCenterLine[i].x2
        let y2 = tmpVertCenterLine[i].y2

        if (i === 2 || i === 4) {
          tmpArray = []
          const prevLine = tmpVertCenterLine[i - 1] //뒤에서 앞라인을 찾는다
          const nextLine = tmpVertCenterLine[i + 1]

          //내 앞뒤 라인
          const tmpX1 = i === 2 ? prevLine.x1 : nextLine.x1
          const tmpY1 = i === 2 ? prevLine.y1 : nextLine.y1
          const tmpX2 = i === 2 ? prevLine.x2 : nextLine.x2
          const tmpY2 = i === 2 ? prevLine.y2 : nextLine.y2

          firstPointObj = { x: tmpX1, y: tmpY1 }
          secondPointObj = { x: tmpX2, y: tmpY2 }
          tmpArray.push(firstPointObj)
          tmpArray.push(secondPointObj)

          //현재 내 선
          firstPointObj = { x: x1, y: y1 }
          secondPointObj = { x: x2, y: y2 }
          tmpArray.push(firstPointObj)
          tmpArray.push(secondPointObj)
          roofPatternPolygonArray.push(tmpArray)
        } else {
          if (i === 1 || i === 5) {
            // 큰 폴리곤은 가운데 선으로 되야됨
            if (outLines.length / 2 < concavePointIndices[0]) {
              //오목이가 배열 전체보다 크면 위쪽 방향
              x2 = i === 1 ? lastCenterLine.x2 : lastCenterLine.x1
              y2 = i === 1 ? lastCenterLine.y2 : lastCenterLine.y1
            } else {
              x1 = i === 1 ? lastCenterLine.x1 : lastCenterLine.x2
              y1 = i === 1 ? lastCenterLine.y1 : lastCenterLine.y2
            }
          }

          if (i === 5) {
            //5번일때는 앞에 3번에 선이 필요하다
            let prevX1 = tmpVertCenterLine[i - 2].x1
            let prevY1 = tmpVertCenterLine[i - 2].y1
            let prevX2 = tmpVertCenterLine[i - 2].x2
            let prevY2 = tmpVertCenterLine[i - 2].y2
            firstPointObj = { x: prevX1, y: prevY1 }
            secondPointObj = { x: prevX2, y: prevY2 }
            tmpBigArray.push(firstPointObj)
            tmpBigArray.push(secondPointObj)
          }

          firstPointObj = { x: x1, y: y1 }
          secondPointObj = { x: x2, y: y2 }
          tmpBigArray.push(firstPointObj)
          tmpBigArray.push(secondPointObj)

          if (i === 3 || i === 6) {
            roofPatternPolygonArray.push(tmpBigArray)
            tmpBigArray = []
          }
        }
      }
      setRoofPolygonPattern({ roofPatternPolygonArray, lines })
    }
    canvas?.renderAll()
  }

  /**
   * 템플릿 B 적용
   */
  const applyTemplateB = () => {
    changeMode(canvas, Mode.EDIT)
    const polygon = drawWallPolygon()
    const params = {
      eaves: 50,
      edge: 20,
      polygon,
    }
    handleInnerLineColor(polygon)
    // handleOuterLineTemplateB(params)
    console.log(polygon.lines.length)
    if (polygon.lines.length === 4) {
      console.log('4각형')
      handleTemplateBRect(params)
    } else if (polygon.lines.length === 6) {
      console.log('6각형')
      handleTemplateB(params)
    }

    setTemplateType(3)
  }

  /**
   * 4각형일때 계산 로직
   * @param {obj} params
   */
  const handleTemplateBRect = (params) => {
    const { eaves, edge, polygon } = params
    const centerLinePoint = {}
    const centerDashLinePoint = {}

    const qlineOpt = {
      stroke: 'blue',
      strokeWidth: 2,
      selectable: false,
      fontSize: fontSize,
    }
    const qlineOptDash = {
      stroke: 'black',
      strokeWidth: 2,
      strokeDashArray: [5, 5],
      selectable: false,
      fontSize: fontSize,
    }
    const qlineOptDashWithoutLength = {
      ...qlineOptDash,
      isActiveLengthText: false,
    }

    const bigRoofPolygon = []
    const middleRoofPolygon = []

    polygon.lines.forEach((line, index) => {
      let outline
      if (index === 0) {
        outline = new QLine([line.x1 - edge, line.y1 - eaves, line.x2 - edge, line.y2 + eaves], qlineOpt)
        const centeredPoint = getCenterPoint(line.y1, line.y2)
        centerLinePoint.x1 = line.x1 - edge
        centerLinePoint.y1 = centeredPoint
        centerLinePoint.y2 = centeredPoint
        centerDashLinePoint.y1 = line.y1 - eaves
        centerDashLinePoint.y2 = line.y2 + eaves
        bigRoofPolygon[0] = { x: line.x1 - edge, y: line.y1 - eaves }
        middleRoofPolygon[0] = { x: line.x1 - edge, y: centeredPoint }
        middleRoofPolygon[1] = { x: line.x2 - edge, y: line.y2 + eaves }
      } else if (index === 1) {
        outline = new QLine([line.x1 - edge, line.y1 + eaves, line.x2 + edge, line.y2 + eaves], qlineOpt)
        const centeredPoint = getCenterPoint(line.x1, line.x2)
        centerLinePoint.x2 = line.x2 + edge
        centerDashLinePoint.x1 = centeredPoint
        centerDashLinePoint.x2 = centeredPoint
      } else if (index === 2) {
        outline = new QLine([line.x1 + edge, line.y1 + eaves, line.x2 + edge, line.y2 - eaves], qlineOpt)
        bigRoofPolygon[3] = { x: line.x2 + edge, y: line.y2 - eaves }
        middleRoofPolygon[2] = { x: line.x1 + edge, y: line.y1 + eaves }
      } else if (index === 3) {
        outline = new QLine([line.x1 + edge, line.y1 - eaves, line.x2 - edge, line.y2 - eaves], qlineOpt)
      }
      canvas.add(outline)
    })
    const centerLine = new QLine([centerLinePoint.x1, centerLinePoint.y1, centerLinePoint.x2, centerLinePoint.y2], qlineOpt)
    canvas.add(centerLine)
    const centerDashLine1 = new QLine(
      [centerDashLinePoint.x1, centerDashLinePoint.y1, centerDashLinePoint.x2, getCenterPoint(centerDashLinePoint.y1, centerDashLinePoint.y2)],
      qlineOptDashWithoutLength,
    )
    canvas.add(centerDashLine1)
    const centerDashLine2 = new QLine(
      [centerDashLinePoint.x1, getCenterPoint(centerDashLinePoint.y1, centerDashLinePoint.y2), centerDashLinePoint.x2, centerDashLinePoint.y2],
      qlineOptDashWithoutLength,
    )
    canvas.add(centerDashLine2)

    bigRoofPolygon[1] = { x: centerLine.x1, y: centerLine.y1 }
    bigRoofPolygon[2] = { x: centerLine.x2, y: centerLine.y2 }

    middleRoofPolygon[3] = { x: centerLinePoint.x2, y: centerLinePoint.y2 }

    const roofPatternPolygonArray = []
    roofPatternPolygonArray.push(bigRoofPolygon)
    roofPatternPolygonArray.push(middleRoofPolygon)
    if (roofPatternPolygonArray.length > 0) {
      setRoofPolygonPattern({ roofPatternPolygonArray, lines: polygon.lines })
    }

    canvas?.renderAll()
  }

  /**
   * 6각형일때 계산 로직
   * @param {obj} params
   */
  const handleTemplateB = (params) => {
    const { eaves, edge, polygon } = params
    // 가장 긴 라인이 첫번째일때
    let shapeType = 0
    console.log(polygon)
    const odd = polygon.lines.filter((line, index) => index % 2 === 0)
    const even = polygon.lines.filter((line, index) => index % 2 !== 0)
    const rerangeOdd = chgLineDirectionVertical(odd)
    const rerangeEven = chgLineDirectionHorizontal(even)
    // 가장 긴 라인이 첫번째인지 판단
    chkLengthIndex({ arr: odd, type: 'L' }) !== 0 ? (shapeType = 1) : null
    // 가장 짧은 라인의 인덱스 반환
    const shortIndex = chkLengthIndex({ arr: odd, type: 'S' })

    const centralLinePoint = {
      x1: 0,
      y1: 0,
      x2: 0,
      y2: 0,
    }
    const centralSubLinePoint = {
      x1: 0,
      y1: 0,
      x2: 0,
      y2: 0,
    }
    const centralDashLinePoint = {
      x1: 0,
      y1: 0,
      x2: 0,
      y2: 0,
    }
    const centralSubDashLinePoint = {
      x1: 0,
      y1: 0,
      x2: 0,
      y2: 0,
    }
    const qlineOpt = {
      stroke: 'blue',
      strokeWidth: 2,
      selectable: false,
      fontSize: fontSize,
    }
    const qlineOptDash = {
      stroke: 'black',
      strokeWidth: 2,
      strokeDashArray: [5, 5],
      selectable: false,
      fontSize: fontSize,
    }

    /**
     * 지붕 패턴을 위한 폴리곤 좌표 생성
     */
    const bigRoofPolygon = []
    const middleRoofPolygon = []
    const smallRoofPolygon = []

    rerangeOdd.forEach((line, index) => {
      const centeredPoint = getCenterPoint(line.y1, line.y2)
      let points1 = []
      let points2 = []
      if (polygon.shape === 2 || polygon.shape === 3) {
        if (index === 0) {
          points1 = [line.x1 - edge, line.y1 - eaves, line.x1 - edge, centeredPoint]
          points2 = [line.x2 - edge, centeredPoint, line.x2 - edge, line.y2 + eaves]
          centralLinePoint.x1 = line.x1 - edge
          centralLinePoint.y1 = centeredPoint
          centralLinePoint.y2 = centeredPoint
          centralDashLinePoint.y1 = line.y1 - eaves
          centralDashLinePoint.y2 = line.y2 + eaves
          if (polygon.shape === 2) {
            middleRoofPolygon[0] = { x: line.x1 - edge, y: line.y1 - eaves }
            middleRoofPolygon[1] = { x: line.x1 - edge, y: centeredPoint }
          } else {
            bigRoofPolygon[1] = { x: line.x1 - edge, y: centeredPoint }
            bigRoofPolygon[0] = { x: line.x1 - edge, y: line.y1 - eaves }
            middleRoofPolygon[1] = { x: line.x2 - edge, y: line.y2 + eaves }
          }
        } else if (index === 1) {
          if (polygon.shape === 2) {
            points1 = [line.x1 + edge, line.y1 - eaves, line.x1 + edge, centeredPoint]
            points2 = [line.x1 + edge, centeredPoint, line.x2 + edge, line.y2 + eaves]
            centralSubLinePoint.x2 = line.x1 + edge
            centralSubLinePoint.y2 = centeredPoint
            bigRoofPolygon[2] = { x: line.x2 + edge, y: line.y2 + eaves }
            bigRoofPolygon[3] = { x: line.x2 + edge, y: centeredPoint }
            smallRoofPolygon[0] = { x: line.x1 + edge, y: centeredPoint }
            smallRoofPolygon[1] = { x: line.x1 + edge, y: line.y1 - eaves }
          } else {
            points1 = [line.x1 + edge, getCenterPoint(rerangeOdd[2].y1, rerangeOdd[2].y2), line.x2 + edge, line.y2 + eaves]
            points2 = [line.x1, getCenterPoint(rerangeOdd[2].y1, rerangeOdd[2].y2), line.x1, line.y1 + eaves]
            centralLinePoint.x2 = line.x1 + edge
            centralSubLinePoint.y1 = getCenterPoint(rerangeOdd[2].y1, rerangeOdd[2].y2)
            centralSubLinePoint.y2 = getCenterPoint(rerangeOdd[2].y1, rerangeOdd[2].y2)
            bigRoofPolygon[3] = { x: line.x1 + edge, y: centralSubLinePoint.y1 }
            middleRoofPolygon[2] = { x: line.x2 + edge, y: line.y2 + eaves }
            smallRoofPolygon[0] = { x: line.x1, y: centralSubLinePoint.y1 }
            smallRoofPolygon[1] = { x: line.x1, y: line.y1 + eaves }
          }
        } else if (index === 2) {
          if (polygon.shape === 2) {
            points1 = [line.x1 + edge, line.y1 - eaves, line.x2 + edge, centralSubLinePoint.y2]
            points2 = [line.x2, line.y2 - eaves, line.x2, centralSubLinePoint.y2]
            bigRoofPolygon[4] = { x: line.x2 + edge, y: centralSubLinePoint.y2 }
            middleRoofPolygon[3] = { x: line.x1 + edge, y: line.y1 - eaves }
            smallRoofPolygon[2] = { x: line.x2, y: line.y2 - eaves }
            smallRoofPolygon[3] = { x: line.x2, y: centralSubLinePoint.y2 }
          } else {
            points1 = [line.x1 + edge, line.y1 - eaves, line.x2 + edge, centeredPoint]
            points2 = [line.x2 + edge, centeredPoint, line.x2 + edge, line.y2 + eaves]
            bigRoofPolygon[4] = { x: line.x1 + edge, y: centralSubLinePoint.y2 }
            bigRoofPolygon[5] = { x: line.x1 + edge, y: line.y1 - eaves }
            smallRoofPolygon[2] = { x: line.x2 + edge, y: line.y2 + eaves }
            smallRoofPolygon[3] = { x: line.x2 + edge, y: centeredPoint }
          }
        }
      } else {
        if (index === 0) {
          points1 = [line.x1 - edge, line.y1 - eaves, line.x2 - edge, line.y2 + eaves]
          centralSubLinePoint.x1 = line.x1 - edge
          centralSubLinePoint.y1 = getCenterPoint(line.y1, line.y2)
          centralSubLinePoint.y2 = getCenterPoint(line.y1, line.y2)
          if (polygon.shape === 1) {
            bigRoofPolygon[0] = { x: line.x1 - edge, y: line.y1 - eaves }
            bigRoofPolygon[1] = { x: line.x1 - edge, y: getCenterPoint(line.y1, line.y2) }
            smallRoofPolygon[0] = { x: line.x1 - edge, y: getCenterPoint(line.y1, line.y2) }
            smallRoofPolygon[1] = { x: line.x2 - edge, y: line.y2 + eaves }
          } else {
            bigRoofPolygon[0] = { x: line.x1 - edge, y: centeredPoint }
            bigRoofPolygon[1] = { x: line.x1 - edge, y: line.y2 + eaves }
            smallRoofPolygon[0] = { x: line.x1 - edge, y: line.y1 - eaves }
            smallRoofPolygon[1] = { x: centralSubLinePoint.x1, y: centralSubLinePoint.y1 }
          }
        } else if (index === 1) {
          if (polygon.shape === 1) {
            points1 = [line.x1 - edge, centralSubLinePoint.y1, line.x2 - edge, line.y2 + eaves]
            points2 = [line.x1, centralSubLinePoint.y1, line.x1, line.y1 + eaves]
            centralLinePoint.x1 = line.x1 - edge
            centralSubLinePoint.x2 = line.x2
            bigRoofPolygon[2] = { x: line.x1 - edge, y: centralSubLinePoint.y2 }
            middleRoofPolygon[1] = { x: line.x2 - edge, y: line.y2 + eaves }
            smallRoofPolygon[2] = { x: line.x1, y: line.y1 + eaves }
          } else {
            points1 = [line.x1 + edge, line.y1 - eaves, line.x2 + edge, centeredPoint]
            points2 = [line.x2 + edge, centeredPoint, line.x2 + edge, line.y2 + eaves]
            centralLinePoint.x2 = line.x1 + edge
            centralLinePoint.y1 = centeredPoint
            centralLinePoint.y2 = centeredPoint
            centralDashLinePoint.y1 = line.y1 - eaves
            centralDashLinePoint.y2 = line.y2 + eaves
            bigRoofPolygon[2] = { x: line.x2 + edge, y: line.y2 + eaves }
            bigRoofPolygon[3] = { x: line.x2 + edge, y: centralLinePoint.y2 }
            middleRoofPolygon[3] = { x: line.x1 + edge, y: line.y1 - eaves }
          }
        } else {
          if (polygon.shape === 1) {
            points1 = [line.x1 + edge, line.y1 - eaves, line.x1 + edge, centeredPoint]
            points2 = [line.x2 + edge, centeredPoint, line.x2 + edge, line.y2 + eaves]
            centralLinePoint.x2 = line.x1 + edge
            centralLinePoint.y1 = centeredPoint
            centralLinePoint.y2 = centeredPoint
            centralDashLinePoint.y1 = line.y1 - eaves
            centralDashLinePoint.y2 = line.y2 + eaves
            bigRoofPolygon[5] = { x: line.x1 + edge, y: line.y1 - eaves }
            middleRoofPolygon[2] = { x: line.x2 + edge, y: line.y2 + eaves }
          } else {
            points1 = [line.x1 - edge, line.y1 - eaves, line.x2 - edge, centralSubLinePoint.y1]
            points2 = [line.x2, line.y2 - eaves, line.x2, centralSubLinePoint.y2]
            centralLinePoint.x1 = line.x1 - edge
            centralSubLinePoint.x2 = line.x2
            bigRoofPolygon[4] = { x: line.x2 - edge, y: centralLinePoint.y1 }
            bigRoofPolygon[5] = { x: line.x2 - edge, y: centralSubLinePoint.y2 }
            middleRoofPolygon[0] = { x: line.x1 - edge, y: line.y1 - eaves }
            smallRoofPolygon[2] = { x: line.x2, y: centralSubLinePoint.y2 }
            smallRoofPolygon[3] = { x: line.x2, y: line.y2 - eaves }
          }
        }
      }

      if (points1.length > 0) {
        const subLine1 = new QLine(points1, qlineOpt)
        canvas.add(subLine1)
      }
      if (points2.length > 0) {
        const subLine2 = new QLine(points2, qlineOpt)
        canvas.add(subLine2)
      }
    })

    rerangeEven.forEach((line, index) => {
      let points = []
      if (polygon.shape === 2 || polygon.shape === 3) {
        if (index === 0) {
          points = [line.x1 - edge, line.y1 + eaves, line.x2 + edge, line.y2 + eaves]
          if (polygon.shape === 3) {
            centralDashLinePoint.x1 = getCenterPoint(line.x1, line.x2)
            centralDashLinePoint.x2 = getCenterPoint(line.x1, line.x2)
          }
        } else if (index === 2) {
          points = [line.x1 - edge, line.y1 - eaves, line.x2 + edge, line.y2 - eaves]
          if (polygon.shape === 2) {
            centralDashLinePoint.x1 = getCenterPoint(line.x1, line.x2)
            centralDashLinePoint.x2 = getCenterPoint(line.x1, line.x2)
            centralLinePoint.x2 = line.x2 + edge
          }
        } else {
          if (polygon.shape === 2) {
            const subLines = [
              [line.x1, line.y1 - eaves, line.x2 + edge, line.y2 - eaves],
              [line.x1, centralSubLinePoint.y2, centralSubLinePoint.x2, centralSubLinePoint.y2],
            ]
            subLines.forEach((sLine, index) => {
              const subLine = new QLine(sLine, qlineOpt)
              canvas.add(subLine)
            })
            centralSubDashLinePoint.x1 = getCenterPoint(line.x1, line.x2 + edge)
            centralSubDashLinePoint.x2 = getCenterPoint(line.x1, line.x2 + edge)
            centralSubDashLinePoint.y1 = line.y1 - eaves
            centralSubDashLinePoint.y2 = centralSubLinePoint.y2
          } else {
            const subLines = [
              [line.x1, line.y1 + eaves, line.x2 + edge, line.y2 + eaves],
              [line.x1, centralSubLinePoint.y1, line.x2 + edge, centralSubLinePoint.y2],
            ]
            subLines.forEach((sLine, index) => {
              const subLine = new QLine(sLine, qlineOpt)
              canvas.add(subLine)
            })
            centralSubDashLinePoint.x1 = getCenterPoint(line.x1, line.x2 + edge)
            centralSubDashLinePoint.x2 = getCenterPoint(line.x1, line.x2 + edge)
            centralSubDashLinePoint.y1 = centralSubLinePoint.y1
            centralSubDashLinePoint.y2 = line.y2 + eaves
          }
        }
      } else {
        if (index === 0) {
          if (polygon.shape === 1) {
            const subLines = [
              [centralSubLinePoint.x1, centralSubLinePoint.y1, centralSubLinePoint.x2, centralSubLinePoint.y2],
              [line.x1 - edge, line.y1 + eaves, line.x2, line.y1 + eaves],
            ]
            subLines.forEach((sLine, index) => {
              const subLine = new QLine(sLine, qlineOpt)
              canvas.add(subLine)
            })
            centralSubDashLinePoint.x1 = getCenterPoint(line.x1 - edge, line.x2)
            centralSubDashLinePoint.x2 = getCenterPoint(line.x1 - edge, line.x2)
            centralSubDashLinePoint.y1 = centralSubLinePoint.y1
            centralSubDashLinePoint.y2 = line.y2 + eaves
          } else {
            points = [line.x1 - edge, line.y1 + eaves, line.x2 + edge, line.y2 + eaves]
          }
        } else if (index === 1) {
          if (polygon.shape === 1) {
            points = [line.x1 - edge, line.y1 + eaves, line.x2 + edge, line.y2 + eaves]
            centralDashLinePoint.x1 = getCenterPoint(line.x1, line.x2)
            centralDashLinePoint.x2 = getCenterPoint(line.x1, line.x2)
          } else {
            points = [line.x1 - edge, line.y1 - eaves, line.x2 + edge, line.y2 - eaves]
            centralDashLinePoint.x1 = getCenterPoint(line.x1, line.x2)
            centralDashLinePoint.x2 = getCenterPoint(line.x1, line.x2)
          }
        } else {
          if (polygon.shape === 1) {
            points = [line.x1 - edge, line.y1 - eaves, line.x2 + edge, line.y2 - eaves]
          } else {
            const subLines = [
              [centralSubLinePoint.x1, centralSubLinePoint.y1, centralSubLinePoint.x2, centralSubLinePoint.y2],
              [line.x1 - edge, line.y1 - eaves, line.x2, line.y1 - eaves],
            ]
            subLines.forEach((sLine, index) => {
              const subLine = new QLine(sLine, qlineOpt)
              canvas.add(subLine)
            })
            centralSubDashLinePoint.x1 = getCenterPoint(line.x1 - edge, line.x2)
            centralSubDashLinePoint.x2 = getCenterPoint(line.x1 - edge, line.x2)
            centralSubDashLinePoint.y1 = line.y1 - eaves
            centralSubDashLinePoint.y2 = centralSubLinePoint.y2
          }
        }
      }

      if (points.length > 0) {
        const subLine = new QLine(points, qlineOpt)
        canvas.add(subLine)
      }
    })

    const centralLine = new QLine([centralLinePoint.x1, centralLinePoint.y1, centralLinePoint.x2, centralLinePoint.y2], qlineOpt)
    canvas.add(centralLine)
    const centralDashLine1 = new QLine([centralDashLinePoint.x1, centralDashLinePoint.y1, centralDashLinePoint.x1, centralLinePoint.y2], qlineOptDash)
    canvas.add(centralDashLine1)
    const centralDashLine2 = new QLine([centralDashLine1.x2, centralDashLine1.y2, centralDashLinePoint.x2, centralDashLinePoint.y2], qlineOptDash)
    canvas.add(centralDashLine2)
    const centralSubDashLine = new QLine(
      [centralSubDashLinePoint.x1, centralSubDashLinePoint.y1, centralSubDashLinePoint.x2, centralSubDashLinePoint.y2],
      qlineOptDash,
    )
    canvas.add(centralSubDashLine)

    if (polygon.shape === 1) {
      bigRoofPolygon[3] = { x: centralLine.x1, y: centralLine.y1 }
      bigRoofPolygon[4] = { x: centralLine.x2, y: centralLine.y2 }
      middleRoofPolygon[0] = { x: centralLine.x1, y: centralLine.y1 }
      middleRoofPolygon[3] = { x: centralLine.x2, y: centralLine.y2 }
      smallRoofPolygon[3] = { x: centralSubLinePoint.x2, y: centralSubLinePoint.y2 }
    } else if (polygon.shape === 2) {
      bigRoofPolygon[0] = { x: centralLinePoint.x1, y: centralLinePoint.y1 }
      bigRoofPolygon[1] = { x: centralLinePoint.x1, y: centralDashLinePoint.y2 }
      bigRoofPolygon[5] = { x: centralLinePoint.x2, y: centralLinePoint.y2 }
      middleRoofPolygon[2] = { x: centralLine.x2, y: centralLine.y2 }
    } else if (polygon.shape === 3) {
      bigRoofPolygon[2] = { x: centralLine.x2, y: centralLine.y2 }
      middleRoofPolygon[0] = { x: centralLine.x1, y: centralLine.y1 }
      middleRoofPolygon[3] = { x: centralLine.x2, y: centralLine.y2 }
    } else if (polygon.shape === 4) {
      middleRoofPolygon[1] = { x: centralLine.x1, y: centralLine.y1 }
      middleRoofPolygon[2] = { x: centralLine.x2, y: centralLine.y2 }
    }

    const roofPatternPolygonArray = []
    // if (bigRoofPolygon.length > 0 && middleRoofPolygon.length > 0 && smallRoofPolygon.length > 0) {
    roofPatternPolygonArray.push(bigRoofPolygon)
    roofPatternPolygonArray.push(middleRoofPolygon)
    roofPatternPolygonArray.push(smallRoofPolygon)
    setRoofPolygonPattern({ roofPatternPolygonArray, lines: polygon.lines })
    // }

    canvas?.renderAll()
  }

  /**
   * 세로 방샹 라인의 좌표 순서를 위에서 아래로 변경
   * @param {array} arr
   * @returns
   */
  const chgLineDirectionVertical = (arr) => {
    const newArr = arr.map((line, index) => {
      if (line.direction !== 'bottom') {
        const newPoint = { x1: line.x2, y1: line.y2, x2: line.x1, y2: line.y1 }
        return newPoint
      } else {
        return line
      }
    })
    return newArr
  }

  /**
   * 가로 방향 라인의 좌표 순서를 왼쪽에서 오른쪽으로 변경
   * @param {array} arr
   * @returns
   */
  const chgLineDirectionHorizontal = (arr) => {
    const newArr = arr.map((line, index) => {
      if (line.direction !== 'right') {
        const newPoint = { x1: line.x2, y1: line.y2, x2: line.x1, y2: line.y1 }
        return newPoint
      } else {
        return line
      }
    })
    return newArr
  }

  /**
   * 라인 배열 중 가장 긴 라인의 인덱스를 반환합니다.
   */
  const chkLengthIndex = (params) => {
    const { arr, type } = params
    let maxIndex = 0
    for (let i = 1; i < arr.length; i++) {
      if (type === 'L') {
        if (arr[maxIndex].length < arr[i].length) {
          maxIndex = i
        }
      } else {
        if (arr[maxIndex].length > arr[i].length) {
          maxIndex = i
        }
      }
    }
    return maxIndex
  }

  /**
   * 외벽선 색깔을 변경
   * @param {array} polygon
   */
  const handleInnerLineColor = (polygon) => {
    polygon.lines.forEach((line, index) => {
      if (index % 2 === 0) {
        line.set('stroke', 'rgb(0, 220, 221)')
      } else {
        line.set('stroke', 'rgb(0, 224, 61)')
      }

      const overLine = new QLine([line.x1, line.y1, line.x2, line.y2], {
        stroke: line.stroke,
        strokeWidth: 2,
        selectable: false,
        fontSize: fontSize,
        isActiveLengthText: false,
      })
      canvas.add(overLine)
    })
    canvas?.renderAll()
  }

  /**
   * 지붕 패턴 생성 로직
   * @param roofStyle
   */
  const makeRoofPatternPolygon = (roofStyle) => {
    if (Object.keys(roofPolygonPattern).length === 0 && roofPolygonPattern.constructor === Object) {
      alert('객체가 비어있습니다.')
      return
    }

    //내부 선 점선으로 변경 추후에 다시 되돌리는 로직 필요
    roofPolygonPattern.lines.forEach((line, index) => {
      line.line.set('strokeDashArray', [10, 5, 2, 5])
      line.line.set('stroke', 'blue')
      line.line.set('strokeWidth', 1)
    })

    const ratio = window.devicePixelRatio || 1

    const inputPatternSize = { width: 30, height: 20 } //임시 사이즈
    const patternSize = { ...inputPatternSize } // 입력된 값을 뒤집기 위해

    if (templateType === 2) {
      //세로형이면 width height를 바꿈
      ;[patternSize.width, patternSize.height] = [inputPatternSize.height, patternSize.width]
    }

    // 패턴 소스를 위한 임시 캔버스 생성
    const patternSourceCanvas = document.createElement('canvas')
    patternSourceCanvas.width = roofStyle === 2 ? patternSize.width * 2 * ratio : patternSize.width * ratio
    patternSourceCanvas.height = roofStyle === 2 ? patternSize.height * 2 * ratio : patternSize.height * ratio
    const ctx = patternSourceCanvas.getContext('2d')

    // 벽돌 패턴 그리기
    ctx.scale(ratio, ratio)
    ctx.strokeStyle = 'green'
    ctx.lineWidth = 0.4

    // 첫 번째 행 벽돌
    if (roofStyle === 2) {
      patternSize.width = patternSize.width * 2
      patternSize.height = patternSize.height * 2

      //지그재그
      // // 두 번째 행 벽돌
      if (templateType === 2) {
        ctx.strokeRect(0, 0, patternSize.width / 2, patternSize.height)
        ctx.strokeRect(patternSize.width / 2, patternSize.height / 2, patternSize.width / 2, patternSize.height)
      } else if (templateType === 3) {
        ctx.strokeRect(0, 0, patternSize.width, patternSize.height / 2)
        ctx.strokeRect(patternSize.width / 2, patternSize.height / 2, patternSize.width, patternSize.height / 2)
      }
    } else {
      ctx.strokeRect(0, 0, patternSize.width, patternSize.height) // 원패턴일때랑 지그재그일때랑은 다르게 들어가야함
    }

    // 패턴 생성
    const pattern = new fabric.Pattern({
      source: patternSourceCanvas,
      repeat: 'repeat',
    })

    const commonOption = {
      fill: pattern,
      selectable: false,
      fontSize: 15, // fontSize는 필요에 따라 조정
      sort: false,
      lockMovementX: true,
      lockMovementY: true,
      lockRotation: true,
      lockScalingY: true,
      lockScalingX: true,
    }

    let polygonArray = []

    //패턴 폴리곤을 생성 후 배열에 담음
    roofPolygonPattern.roofPatternPolygonArray.forEach((patternPolygon, index) => {
      const drawPolygon = new QPolygon(patternPolygon, commonOption)
      canvas.add(drawPolygon)
      drawPolygon.setViewLengthText(false)
      drawPolygon.set('customIndex', index)
      polygonArray.push(drawPolygon)
    })
    canvas?.renderAll()

    //지붕 폴리곤 recoil에 담음
    setRoofPolygonArray(polygonArray)
  }

  /**
   * 가대 생성 로직
   */
  const makeRoofTrestle = () => {
    if (Object.keys(roofPolygonPattern).length === 0 && roofPolygonPattern.constructor === Object) {
      alert('객체가 비어있습니다.')
      return
    }

    const polygons = roofPolygonArray //리코일에 있는 패턴그린 폴리곤가져옴
    let selectedAreaArray = []

    const defualtStrokeStyle = {
      stroke: 'red',
      strokeDashArray: [9, 5],
      strokeWidth: 0.3,
    }

    const selectedStrokeStyle = {
      stroke: 'red',
      strokeWidth: 3,
    }

    /**
     * 지붕가대 생성 후 가대 선택 이벤트를 추가하는 로직
     * @param polygon
     */
    function toggleSelection(polygon) {
      if (polygon.strokeWidth === defualtStrokeStyle.strokeWidth) {
        //기본 선택이랑 스트로크 굵기가 같으면 선택 안됨으로 봄
        polygon.set({
          stroke: selectedStrokeStyle.stroke,
          strokeWidth: selectedStrokeStyle.strokeWidth,
          strokeDashArray: [0],
        })
        canvas.discardActiveObject() // 객체의 활성 상태 해제
        selectedAreaArray.push(polygon)
      } else {
        //선택후 재선택하면 선택안됨으로 변경
        polygon.set({
          stroke: defualtStrokeStyle.stroke,
          strokeWidth: defualtStrokeStyle.strokeWidth,
          strokeDashArray: defualtStrokeStyle.strokeDashArray,
        })
        canvas.discardActiveObject() // 객체의 활성 상태 해제

        //폴리곤에 커스텀 인덱스를 가지고 해당 배열 인덱스를 찾아 삭제함
        const removeIndex = polygon.customIndex
        const removeArrayIndex = selectedAreaArray.findIndex((x) => x.customIndex === removeIndex)
        selectedAreaArray.splice(removeArrayIndex, 1)
      }
      canvas?.renderAll()
    }

    //외각선을 안쪽으로 그려 가대선을 그린다.
    polygons.forEach((polygon, index) => {
      const trestlePolygon = handleOuterlinesTest(polygon, -12)
      trestlePolygon.setViewLengthText(false) //얘는 set으로 안먹는다...
      trestlePolygon.set({
        stroke: 'red',
        strokeDashArray: [9, 5],
        strokeWidth: 0.3,
        lockMovementX: true,
        lockMovementY: true,
        lockRotation: true,
        lockScalingX: true,
        lockScalingY: true,
        bringToFront: true,
        customIndex: polygon.customIndex, //가대 폴리곤의 임시 인덱스를 넣어줌
      })

      /**
       * 가대 선택 이벤트
       */
      trestlePolygon.on('mousedown', function () {
        toggleSelection(trestlePolygon)
      })
    })
    setSelectedCellRoofArray(selectedAreaArray)
  }

  /**
   * 가대 선택 후 셀 채우기
   */
  const makeRoofFillCells = () => {
    const drawCellsArray = []

    if (selectedCellRoofArray.length === 0) {
      //배열에 선택된 가대 셀이 없으면 리턴
      alert('선택된 영역이 없습니다.')
      setMode(Mode.DEFAULT) //default 모드로 변경
      return
    }

    if (drewRoofCells.length > 0) {
      //리코일에
      if (confirm('패널이 초기화 됩니다.')) {
        drewRoofCells.forEach((cells, index) => {
          cells.drawCells.forEach((cell) => {
            canvas?.remove(cell)
          })
        })
        setDrewRoofCells([])
        canvas?.renderAll()
      }
    }

    const inputCellSize = { width: 172, height: 113 }
    const cellSize = { ...inputCellSize } //기본으로 가로형으로 넣고

    if (templateType === 2) {
      ;[cellSize.width, cellSize.height] = [cellSize.height, cellSize.width]
    }

    selectedCellRoofArray.forEach((polygon, index) => {
      const drawCells = polygon.fillCell({ width: cellSize.width, height: cellSize.height, padding: 10 })
      drawCellsArray.push({ roofIndex: polygon.customIndex, drawCells: drawCells })
    })

    setDrewRoofCells(drawCellsArray)
    setMode(Mode.DEFAULT) //default 모드로 변경
  }

  return {
    mode,
    setMode,
    changeMode,
    setCanvas,
    handleClear,
    zoomIn,
    zoomOut,
    zoom,
    togglePolygonLine,
    handleOuterlinesTest,
    handleOuterlinesTest2,
    makeRoofPatternPolygon,
    makeRoofTrestle,
  }
}
