import { useCanvas } from '@/hooks/useCanvas'
import { useEffect, useState } from 'react'
import { Mode, useMode } from '@/hooks/useMode'
import { Button } from '@nextui-org/react'
import QRect from '@/components/fabric/QRect'

import RangeSlider from './ui/RangeSlider'
import { useRecoilState, useRecoilValue } from 'recoil'
import { canvasSizeState, fontSizeState, roofMaterialState, roofState, sortedPolygonArray } from '@/store/canvasAtom'
import { QLine } from '@/components/fabric/QLine'
import { getCanvasState, insertCanvasState } from '@/lib/canvas'
import { calculateIntersection } from '@/util/canvas-util'
import { QPolygon } from '@/components/fabric/QPolygon'
import offsetPolygon from '@/util/qpolygon-utils'

export default function Roof2() {
  const { canvas, handleRedo, handleUndo, setCanvasBackgroundWithDots, saveImage, addCanvas } = useCanvas('canvas')

  //canvas 기본 사이즈
  const [canvasSize, setCanvasSize] = useRecoilState(canvasSizeState)

  //canvas 가로 사이즈
  const [verticalSize, setVerticalSize] = useState(canvasSize.vertical)
  //canvas 세로 사이즈
  const [horizontalSize, setHorizontalSize] = useState(canvasSize.horizontal)
  // 글자크기
  const [fontSize, setFontSize] = useRecoilState(fontSizeState)

  const [sortedArray] = useRecoilState(sortedPolygonArray)

  const [angle, setAngle] = useState(0)

  const [showControl, setShowControl] = useState(false)

  //지붕재
  const roofMaterial = useRecoilValue(roofMaterialState)

  const {
    mode,
    setMode,
    changeMode,
    handleClear,
    fillCellInPolygon,
    zoomIn,
    zoomOut,
    zoom,
    togglePolygonLine,
    handleOuterlinesTest,
    handleOuterlinesTest2,
    applyTemplateB,
    makeRoofPatternPolygon,
  } = useMode()

  // const [canvasState, setCanvasState] = useRecoilState(canvasAtom)

  useEffect(() => {
    if (!canvas) {
      return
    }
    changeMode(canvas, mode)
  }, [canvas, mode])

  const makeRect = () => {
    if (canvas) {
      const rect = new QRect({
        left: 100,
        top: 100,
        fill: 'transparent',
        stroke: 'black',
        width: 400,
        height: 100,
        fontSize: fontSize,
      })

      canvas?.add(rect)
    }
  }

  const makeLine = () => {
    if (canvas) {
      const line = new QLine([50, 50, 200, 50], {
        stroke: 'black',
        strokeWidth: 2,
        fontSize: fontSize,
      })

      canvas?.add(line)
    }
  }

  const makePolygon = () => {
    if (canvas) {
      const polygon = new QPolygon(
        [
          { x: 100, y: 100 },
          { x: 600, y: 200 },
          { x: 700, y: 800 },
          { x: 100, y: 800 },
        ],
        {
          fill: 'transparent',
          stroke: 'black',
          strokeWidth: 2,
          selectable: true,
          fontSize: fontSize,
        },
      )
      canvas?.add(polygon)

      // polygon.fillCell({ width: 50, height: 30, padding: 10 })
    }
  }

  useEffect(() => {
    setCanvasSize({ ...canvasSize, vertical: parseInt(verticalSize), horizontal: parseInt(horizontalSize) })
  }, [verticalSize, horizontalSize])

  /**
   * 값 변경시
   */
  // useEffect(() => {
  //   canvasSizeMode()
  // }, [verticalSize, horizontalSize])
  useEffect(() => {
    const { vertical, horizontal } = canvasSize
    if (vertical !== verticalSize || horizontal !== horizontalSize) {
      canvas?.setWidth(horizontalSize)
      canvas?.setHeight(verticalSize)
      canvas?.renderAll()
    }
  }, [canvasSize, canvas])

  const makeQPolygon = () => {
    const type1 = [
      { x: 100, y: 100 },
      { x: 850, y: 100 },
      { x: 850, y: 800 },
      { x: 500, y: 800 },
      { x: 500, y: 400 },
      { x: 100, y: 400 },
    ]
    const type2 = [
      { x: 200, y: 100 },
      { x: 200, y: 1000 },
      { x: 1100, y: 1000 },
      { x: 1100, y: 600 },
      { x: 650, y: 600 },
      { x: 650, y: 100 },
    ]

    const type3 = [
      { x: 200, y: 100 },
      { x: 200, y: 800 },
      { x: 500, y: 800 },
      { x: 500, y: 300 },
      { x: 800, y: 300 },
      { x: 800, y: 100 },
    ]

    const type4 = [
      { x: 150, y: 450 },
      { x: 150, y: 800 },
      { x: 750, y: 800 },
      { x: 750, y: 300 },
      { x: 550, y: 300 },
      { x: 550, y: 450 },
    ]

    const type1A = [
      { x: 67, y: 81 },
      { x: 67, y: 660 },
      { x: 437, y: 660 },
      { x: 437, y: 1190 },
      { x: 858, y: 1190 },
      { x: 858, y: 81 },
    ]

    const type1B = [
      { x: 137, y: 42 },
      { x: 137, y: 621 },
      { x: 667, y: 621 },
      { x: 667, y: 991 },
      { x: 1088, y: 991 },
      { x: 1088, y: 42 },
    ]

    const eightPoint = [
      { x: 240.1111, y: 130.1111 },
      { x: 240.1111, y: 630.1111 },
      { x: 640.1111, y: 630.1111 },
      { x: 640.1111, y: 480.1111 },
      { x: 440.1111, y: 480.1111 },
      { x: 440.1111, y: 280.1111 },
      { x: 740.1111, y: 280.1111 },
      { x: 740.1111, y: 130.1111 },
    ]

    const eightPoint2 = [
      { x: 197, y: 215 },
      { x: 197, y: 815 },
      { x: 397, y: 815 },
      { x: 397, y: 1115 },
      { x: 697, y: 1115 },
      { x: 697, y: 815 },
      { x: 897, y: 815 },
      { x: 897, y: 215 },
    ]

    const eightPoint3 = [
      { x: 190, y: 147 },
      { x: 190, y: 747 },
      { x: 490, y: 747 },
      { x: 490, y: 497 },
      { x: 640, y: 497 },
      { x: 640, y: 747 },
      { x: 1090, y: 747 },
      { x: 1090, y: 147 },
    ]

    const eightPoint4 = [
      { x: 228, y: 92 },
      { x: 228, y: 592 },
      { x: 478, y: 592 },
      { x: 478, y: 342 },
      { x: 728, y: 342 },
      { x: 728, y: 592 },
      { x: 1078, y: 592 },
      { x: 1078, y: 92 },
    ]

    const twelvePoint = [
      { x: 195, y: 166 },
      { x: 195, y: 466 },
      { x: 395, y: 466 },
      { x: 395, y: 766 },
      { x: 545, y: 766 },
      { x: 545, y: 466 },
      { x: 695, y: 466 },
      { x: 695, y: 666 },
      { x: 845, y: 666 },
      { x: 845, y: 466 },
      { x: 995, y: 466 },
      { x: 995, y: 166 },
    ]

    const complicatedType = [
      { x: 100, y: 100 },
      { x: 100, y: 1100 },
      { x: 400, y: 1100 },
      { x: 400, y: 800 },
      { x: 700, y: 800 },
      { x: 700, y: 1100 },
      { x: 1000, y: 1100 },
      { x: 1000, y: 600 },
      { x: 700, y: 600 },
      { x: 700, y: 300 },
      { x: 1000, y: 300 },
      { x: 1000, y: 100 },
    ]

    const types = [type1, type2, type3, type4, type1A, type1B, eightPoint, eightPoint2, eightPoint3, eightPoint4, twelvePoint]
    const newP = [
      { x: 450, y: 450 },
      { x: 650, y: 250 },
      { x: 675, y: 275 },
      { x: 450, y: 850 },
    ]
    const polygon = new QPolygon(type2, {
      fill: 'transparent',
      stroke: 'black',
      strokeWidth: 1,
      selectable: false,
      fontSize: fontSize,
      name: 'wall',
    })

    canvas?.add(polygon)
    handleOuterlinesTest2(polygon)
    // const lines = togglePolygonLine(polygon)
    // togglePolygonLine(lines[0])
  }

  const rotateShape = () => {
    if (canvas) {
      const activeObject = canvas?.getActiveObject()

      if (activeObject) {
        activeObject.rotate(angle)
        canvas?.renderAll()
      }
    }
  }

  const makeQLine = () => {
    if (canvas) {
      const line = new QLine([50, 250, 900, 250], {
        stroke: 'black',
        strokeWidth: 5,
        fontSize: fontSize,
        selectable: true,
      })

      const line2 = new QLine([450, 450, 821, 78], {
        stroke: 'black',
        strokeWidth: 5,
        fontSize: fontSize,
        selectable: true,
      })

      canvas?.add(line)
      canvas?.add(line2)

      const interSectionPoint = calculateIntersection(line, line2)

      if (interSectionPoint) {
        const circle = new fabric.Circle({
          radius: 5,
          fill: 'red',
          left: interSectionPoint.x - 5,
          top: interSectionPoint.y - 5,
        })

        canvas?.add(circle)
      }
    }
  }

  const addBackgroundInPolygon = (polygon) => {
    fabric.Image.fromURL('assets/img/check2.png', function (img) {
      // 패턴 객체를 생성합니다.
      const pattern = new fabric.Pattern({
        source: img.getElement(),
        repeat: 'repeat',
      })

      polygon.fillBackground(pattern)
    })
  }

  function PolygonToLine() {
    const polygon = canvas?.getActiveObject()

    if (polygon.type !== 'QPolygon') {
      return
    }

    const lines = togglePolygonLine(polygon)
  }

  /**
   * canvas 내용 저장하기
   */
  const handleSaveCanvas = async () => {
    // const jsonStr = JSON.stringify(canvas?.toDatalessJSON(['type', 'fontSize']))
    const jsonObj = JSON.stringify(canvas?.toDatalessJSON(['type', 'fontSize', 'lines']))
    console.log(jsonObj)

    const param = {
      loginId: 'test',
      canvas: jsonObj,
    }
    console.log(param)

    await insertCanvasState(param)
    handleClear()
  }

  const drawRoofMaterial = () => {
    const { width, height, roofStyle } = roofMaterial

    const wallPolygon = canvas?.getObjects().find((obj) => obj.name === 'wall')

    wallPolygon.set('strokeDashArray', [10, 5, 2, 5])
    wallPolygon.set('stroke', 'blue')
    wallPolygon.set('strokeWidth', 1)

    const roofs = canvas?.getObjects().filter((obj) => obj.name === 'roof')

    roofs.forEach((roof) => {
      let maxLengthLine = roof.lines.reduce((acc, cur) => {
        return acc.length > cur.length ? acc : cur
      })

      const roofRatio = window.devicePixelRatio || 1

      // 패턴 소스를 위한 임시 캔버스 생성
      const patternSourceCanvas = document.createElement('canvas')
      if (roofStyle === 1) {
        if (maxLengthLine.direction === 'right' || maxLengthLine.direction === 'left') {
          patternSourceCanvas.width = width * roofRatio
          patternSourceCanvas.height = height * roofRatio
        } else {
          patternSourceCanvas.width = height * roofRatio
          patternSourceCanvas.height = width * roofRatio
        }
      } else if (roofStyle === 2) {
        if (maxLengthLine.direction === 'right' || maxLengthLine.direction === 'left') {
          patternSourceCanvas.width = width * 2
          patternSourceCanvas.height = height * 2
        } else {
          patternSourceCanvas.width = height * 2
          patternSourceCanvas.height = width * 2
        }
      }

      const ctx = patternSourceCanvas.getContext('2d')

      ctx.scale(roofRatio, roofRatio)
      ctx.strokeStyle = 'green'
      ctx.lineWidth = 0.4
      // 벽돌 패턴 그리기
      if (roofStyle === 1) {
        ctx.strokeRect(0, 0, 50, 30)
      } else if (roofStyle === 2) {
        // 지그재그
        ctx.strokeRect(0, 0, 200, 100)
        ctx.strokeRect(100, 100, 200, 100)
      }

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

      roof.set('fill', pattern)
      canvas?.renderAll()
    })
  }

  /**
   * canvas 내용 불러오기
   */
  const handleLoadCanvas = async () => {
    const canvasStates = await getCanvasState()
    console.log(JSON.parse(canvasStates.canvas))
    canvas?.loadFromJSON(JSON.parse(canvasStates.canvas))
  }

  /**
   * 컨트롤러 보이기/숨기기
   */
  const handleShowController = () => {
    setShowControl(!showControl)
  }

  const drawRoofPatterns = (roofStyle) => {
    makeRoofPatternPolygon(roofStyle)
  }

  const createRoofRack = () => {
    const roofs = canvas?.getObjects().filter((obj) => obj.name === 'roof')
    roofs.forEach((roof) => {
      let maxLengthLine = roof.lines.reduce((acc, cur) => {
        return acc.length > cur.length ? acc : cur
      })

      const offsetPolygonPoint = offsetPolygon(roof.points, -20, 0)

      const newPoly = new QPolygon(offsetPolygonPoint, {
        fill: 'transparent',
        stroke: 'red',
        strokeWidth: 1,
        selectable: true,
        fontSize: fontSize,
        name: 'wall',
      })

      canvas?.add(newPoly)

      if (maxLengthLine.direction === 'right' || maxLengthLine.direction === 'left') {
        newPoly.fillCell({ width: 100, height: 50, padding: 10 })
      } else {
        newPoly.fillCell({ width: 50, height: 100, padding: 10 })
      }
    })
  }

  return (
    <>
      {canvas && (
        <>
          <div className=" my-8 w-full text:pretty">
            <Button className="m-1 p-2" color={`${mode === Mode.DEFAULT ? 'primary' : 'default'}`} onClick={fillCellInPolygon}>
              모드 DEFAULT
            </Button>
            <Button className="m-1 p-2" color={`${mode === Mode.DRAW_LINE ? 'primary' : 'default'}`} onClick={() => setMode(Mode.DRAW_LINE)}>
              기준선 긋기 모드
            </Button>
            <Button className="m-1 p-2" color={`${mode === Mode.EDIT ? 'primary' : 'default'}`} onClick={() => setMode(Mode.EDIT)}>
              에디팅모드
            </Button>
            <Button className="m-1 p-2" color={`${mode === Mode.TEMPLATE ? 'primary' : 'default'}`} onClick={() => setMode(Mode.TEMPLATE)}>
              템플릿(기둥)
            </Button>
            <Button className="m-1 p-2" color={`${mode === Mode.TEMPLATE ? 'primary' : 'default'}`} onClick={() => setMode(Mode.PATTERNA)}>
              템플릿(A 패턴)
            </Button>
            <Button className="m-1 p-2" color={`${mode === Mode.TEMPLATE ? 'primary' : 'default'}`} onClick={() => setMode(Mode.PATTERNB)}>
              템플릿(B 패턴)
            </Button>
            <Button className="m-1 p-2" color={`${mode === Mode.TEMPLATE ? 'primary' : 'default'}`} onClick={() => drawRoofPatterns(1)}>
              지붕패턴1
            </Button>
            <Button className="m-1 p-2" color={`${mode === Mode.TEMPLATE ? 'primary' : 'default'}`} onClick={() => drawRoofPatterns(2)}>
              지붕패턴2
            </Button>
            <Button className="m-1 p-2" color={`${mode === Mode.TEMPLATE ? 'primary' : 'default'}`} onClick={() => setMode(Mode.ROOF_TRESTLE)}>
              지붕가대생성
            </Button>
            <Button className="m-1 p-2" color={`${mode === Mode.TEMPLATE ? 'primary' : 'default'}`} onClick={() => setMode(Mode.FILL_CELLS)}>
              태양광셀생성
            </Button>
            <Button className="m-1 p-2" color={`${mode === Mode.TEXTBOX ? 'primary' : 'default'}`} onClick={() => setMode(Mode.TEXTBOX)}>
              텍스트박스 모드
            </Button>
            <Button className="m-1 p-2" color={`${mode === Mode.DRAW_RECT ? 'primary' : 'default'}`} onClick={() => setMode(Mode.DRAW_RECT)}>
              사각형 생성 모드
            </Button>
            <Button className="m-1 p-2" onClick={handleUndo}>
              Undo
            </Button>
            <Button className="m-1 p-2" onClick={handleRedo}>
              Redo
            </Button>
            <Button className="m-1 p-2" onClick={handleClear}>
              clear
            </Button>
            <Button className="m-1 p-2" onClick={zoomIn}>
              확대
            </Button>
            <Button className="m-1 p-2" onClick={zoomOut}>
              축소
            </Button>
            현재 줌 : {zoom}%
            <Button className="m-1 p-2" onClick={makeRect}>
              사각형만들기
            </Button>
            <Button className="m-1 p-2" onClick={makeLine}>
              선 추가
            </Button>
            <Button className="m-1 p-2" onClick={makePolygon}>
              다각형 추가
            </Button>
            <Button
              className="m-1 p-2"
              onClick={() => {
                setCanvasBackgroundWithDots(canvas, 10)
              }}
            >
              점선 추가
            </Button>
            <Button
              className="m-1 p-2"
              onClick={() => {
                setCanvasBackgroundWithDots(canvas, 20)
              }}
            >
              점선 추가
            </Button>
            <Button className="m-1 p-2" onClick={saveImage}>
              저장
            </Button>
            <Button className="m-1 p-2" onClick={makeQPolygon}>
              QPolygon
            </Button>
            <Button className="m-1 p-2" onClick={rotateShape}>
              회전
            </Button>
            <Button className="m-1 p-2" onClick={makeQLine}>
              QLine
            </Button>
            <Button className="m-1 p-2" onClick={PolygonToLine}>
              PolygonToLine
            </Button>
            {/*<Button className="m-1 p-2" onClick={handleSaveCanvas}>
              canvas 내용 저장하기
            </Button>
            <Button className="m-1 p-2" onClick={handleLoadCanvas}>
              canvas 내용 불러오기
            </Button>*/}
            <Button className="m-1 p-2" onClick={addCanvas}>
              캔버스 추가
            </Button>
            <Button className="m-1 p-2" onClick={drawRoofMaterial}>
              지붕타입 지붕재
            </Button>
            <Button className="m-1 p-2" onClick={createRoofRack}>
              지붕가대
            </Button>
            <Button className="m-1 p-2" color={`${showControl ? 'primary' : 'default'}`} onClick={handleShowController}>
              canvas 컨트롤러 {`${showControl ? '숨기기' : '보이기'}`}
            </Button>
          </div>
          <div className={showControl ? `flex justify-center flex-col items-center` : `hidden`}>
            <div className="m-2 p-2 w-80">
              <RangeSlider title={`각도${angle}`} initValue={angle} min="0" step="1" max="360" onchange={setAngle} />
            </div>
            <div className="m-2 p-2 w-80">
              <RangeSlider
                title={`canvas 가로 사이즈${horizontalSize}`}
                initValue={horizontalSize}
                min="500"
                step="100"
                max="2000"
                onchange={setHorizontalSize}
              />
            </div>
            <div className="m-2 p-2 w-80">
              <RangeSlider
                title={`canvas 세로 사이즈${verticalSize}`}
                initValue={verticalSize}
                min="500"
                step="100"
                max="2000"
                onchange={setVerticalSize}
              />
            </div>
            <div className="m-2 p-2 w-80">
              <RangeSlider title={`글자 크기${fontSize}`} initValue={fontSize} onchange={setFontSize} />
            </div>
          </div>
        </>
      )}
      <div className="flex justify-start my-8 mx-2 w-full">
        <canvas id="canvas" style={{ border: '1px solid black' }} />
      </div>
    </>
  )
}
