'use client'

import { useEffect, useRef } from 'react'
import WithDraggable from '@/components/common/draggable/withDraggable'
import { useRecoilState, useRecoilValue } from 'recoil'
import { useMessage } from '@/hooks/useMessage'
import { useEvent } from '@/hooks/useEvent'
import { canvasState } from '@/store/canvasAtom'
import {
  OUTER_LINE_TYPE,
  outerLineArrow1State,
  outerLineArrow2State,
  outerLineLength1State,
  outerLineLength2State,
  outerLinePointsState,
  outerLineTypeState,
} from '@/store/outerLineAtom'
import { QLine } from '@/components/fabric/QLine'
import { useLine } from '@/hooks/useLine'

export default function OuterLineWall(props) {
  const { showOutlineModal, setShowOutlineModal } = props
  const { getMessage } = useMessage()
  const { addCanvasMouseEventListener, addDocumentEventListener, removeAllDocumentEventListeners } = useEvent()
  const { addLineText, removeLineText } = useLine()
  const length1Ref = useRef(null)
  const length2Ref = useRef(null)
  const [length1, setLength1] = useRecoilState(outerLineLength1State)
  const [length2, setLength2] = useRecoilState(outerLineLength2State)
  const [arrow1, setArrow1] = useRecoilState(outerLineArrow1State)
  const [arrow2, setArrow2] = useRecoilState(outerLineArrow2State)
  const [points, setPoints] = useRecoilState(outerLinePointsState)
  const [type, setType] = useRecoilState(outerLineTypeState)
  const arrow1Ref = useRef(arrow1)
  const arrow2Ref = useRef(arrow2)

  const canvas = useRecoilValue(canvasState)

  useEffect(() => {
    addCanvasMouseEventListener('mouse:down', mouseDown)
  }, [])

  useEffect(() => {
    arrow1Ref.current = arrow1
  }, [arrow1])

  useEffect(() => {
    arrow2Ref.current = arrow2
  }, [arrow2])

  useEffect(() => {
    removeAllDocumentEventListeners()
    addDocumentEventListener('keydown', document, keydown[type])
    clear()
  }, [type])

  const clear = () => {
    setLength1(0)
    setLength2(0)

    setArrow1('')
    setArrow2('')
  }

  const mouseDown = (e) => {
    const pointer = canvas.getPointer(e.e)

    setPoints((prev) => [...prev, pointer])
  }

  useEffect(() => {
    canvas
      ?.getObjects()
      .filter((obj) => obj.name === 'outerLine')
      .forEach((obj) => {
        canvas?.remove(obj)
        removeLineText(obj)
      })
    canvas?.remove(canvas?.getObjects().find((obj) => obj.name === 'startPoint'))
    if (points.length === 0) {
      return
    }

    if (points.length === 1) {
      const point = new fabric.Circle({
        radius: 5,
        fill: 'transparent',
        stroke: 'red',
        left: points[0].x - 5,
        top: points[0].y - 5,
        selectable: false,
        name: 'startPoint',
      })

      canvas?.add(point)
    } else {
      points.forEach((point, idx) => {
        if (idx === 0) {
          return
        }
        drawLine(points[idx - 1], point, idx)
      })
    }
  }, [points])

  const drawLine = (point1, point2, idx) => {
    const line = new QLine([point1.x, point1.y, point2.x, point2.y], {
      stroke: 'black',
      strokeWidth: 1,
      idx: idx,
      selectable: false,
      name: 'outerLine',
    })

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

  // 직각 완료될 경우 확인
  const checkRightAngle = () => {
    const length1Num = Number(length1Ref.current.value) / 10
    const length2Num = Number(length2Ref.current.value) / 10

    if (points.length === 0) {
      return
    }

    if (length1Num === 0 || length2Num === 0 || arrow1Ref.current === '' || arrow2Ref.current === '') {
      return
    }

    if (arrow1Ref.current === '↓' && arrow2Ref.current === '→') {
      setPoints((prev) => {
        if (prev.length === 0) {
          return []
        }
        return [...prev, { x: prev[prev.length - 1].x + length2Num, y: prev[prev.length - 1].y + length1Num }]
      })
    } else if (arrow1Ref.current === '↓' && arrow2Ref.current === '←') {
      setPoints((prev) => {
        if (prev.length === 0) {
          return []
        }
        return [...prev, { x: prev[prev.length - 1].x - length2Num, y: prev[prev.length - 1].y + length1Num }]
      })
    } else if (arrow1Ref.current === '↑' && arrow2Ref.current === '→') {
      setPoints((prev) => {
        if (prev.length === 0) {
          return []
        }
        return [...prev, { x: prev[prev.length - 1].x + length2Num, y: prev[prev.length - 1].y - length1Num }]
      })
    } else if (arrow1Ref.current === '↑' && arrow2Ref.current === '←') {
      setPoints((prev) => {
        if (prev.length === 0) {
          return []
        }
        return [...prev, { x: prev[prev.length - 1].x - length2Num, y: prev[prev.length - 1].y - length1Num }]
      })
    } else if (arrow1Ref.current === '→' && arrow2Ref.current === '↓') {
      setPoints((prev) => {
        if (prev.length === 0) {
          return []
        }
        return [...prev, { x: prev[prev.length - 1].x + length1Num, y: prev[prev.length - 1].y + length2Num }]
      })
    } else if (arrow1Ref.current === '→' && arrow2Ref.current === '↑') {
      setPoints((prev) => {
        if (prev.length === 0) {
          return []
        }
        return [...prev, { x: prev[prev.length - 1].x + length1Num, y: prev[prev.length - 1].y - length2Num }]
      })
    } else if (arrow1Ref.current === '←' && arrow2Ref.current === '↓') {
      setPoints((prev) => {
        if (prev.length === 0) {
          return []
        }
        return [...prev, { x: prev[prev.length - 1].x - length1Num, y: prev[prev.length - 1].y + length2Num }]
      })
    } else if (arrow1Ref.current === '←' && arrow2Ref.current === '↑') {
      setPoints((prev) => {
        if (prev.length === 0) {
          return []
        }
        return [...prev, { x: prev[prev.length - 1].x - length1Num, y: prev[prev.length - 1].y - length2Num }]
      })
    }
  }

  const keydown = {
    outerLine: (e) => {
      const key = e.key

      if (!length1Ref.current) {
        return
      }

      const lengthNum = Number(length1Ref.current.value) / 10
      if (lengthNum === 0) {
        return
      }
      switch (key) {
        case 'Down': // IE/Edge에서 사용되는 값
        case 'ArrowDown': {
          setArrow1('↓')
          setPoints((prev) => {
            if (prev.length === 0) {
              return []
            }
            return [...prev, { x: prev[prev.length - 1].x, y: prev[prev.length - 1].y + lengthNum }]
          })
          break
        }
        case 'Up': // IE/Edge에서 사용되는 값
        case 'ArrowUp':
          setArrow1('↑')
          setPoints((prev) => {
            if (prev.length === 0) {
              return []
            }
            return [...prev, { x: prev[prev.length - 1].x, y: prev[prev.length - 1].y - lengthNum }]
          })
          break
        case 'Left': // IE/Edge에서 사용되는 값
        case 'ArrowLeft':
          setArrow1('←')
          setPoints((prev) => {
            if (prev.length === 0) {
              return []
            }
            return [...prev, { x: prev[prev.length - 1].x - lengthNum, y: prev[prev.length - 1].y }]
          })
          break
        case 'Right': // IE/Edge에서 사용되는 값
        case 'ArrowRight':
          setArrow1('→')
          setPoints((prev) => {
            if (prev.length === 0) {
              return []
            }
            return [...prev, { x: prev[prev.length - 1].x + lengthNum, y: prev[prev.length - 1].y }]
          })
          break
      }
    },
    rightAngle: (e) => {
      const key = e.key

      const activeElem = document.activeElement
      const length1Num = Number(length1Ref.current.value) / 10
      const length2Num = Number(length2Ref.current.value) / 10

      switch (key) {
        case 'Down': // IE/Edge에서 사용되는 값
        case 'ArrowDown': {
          if (activeElem === length1Ref.current) {
            setArrow1('↓')
            arrow1Ref.current = '↓'
            length2Ref.current.focus()
          } else if (activeElem === length2Ref.current) {
            if (arrow1Ref.current === '↓' || arrow1Ref.current === '↑') {
              break
            }
            setArrow2('↓')
            arrow2Ref.current = '↓'
            checkRightAngle()
          }

          break
        }
        case 'Up': // IE/Edge에서 사용되는 값
        case 'ArrowUp':
          if (activeElem === length1Ref.current) {
            setArrow1('↑')
            arrow1Ref.current = '↑'
            length2Ref.current.focus()
          } else if (activeElem === length2Ref.current) {
            if (arrow1Ref.current === '↓' || arrow1Ref.current === '↑') {
              break
            }
            setArrow2('↑')
            arrow2Ref.current = '↑'
            checkRightAngle()
          }

          break
        case 'Left': // IE/Edge에서 사용되는 값
        case 'ArrowLeft':
          if (activeElem === length1Ref.current) {
            setArrow1('←')
            arrow1Ref.current = '←'
            length2Ref.current.focus()
          } else if (activeElem === length2Ref.current) {
            if (arrow1Ref.current === '←' || arrow1Ref.current === '→') {
              break
            }
            setArrow2('←')
            arrow2Ref.current = '←'
            checkRightAngle()
          }

          break
        case 'Right': // IE/Edge에서 사용되는 값
        case 'ArrowRight':
          if (activeElem === length1Ref.current) {
            setArrow1('→')
            arrow1Ref.current = '→'
            length2Ref.current.focus()
          } else if (activeElem === length2Ref.current) {
            if (arrow1Ref.current === '←' || arrow1Ref.current === '→') {
              break
            }
            setArrow2('→')
            arrow2Ref.current = '→'
            checkRightAngle()
          }

          break
      }
    },
    leeGubae: (e) => {
      console.log('leegubae')
    },
    angle: (e) => {
      console.log('angle')
    },
    diagonalLine: (e) => {
      console.log('diagonalLine')
    },
  }

  /**
   * 일변전으로 돌아가기
   */
  const handleRollback = () => {
    //points의 마지막 요소를 제거
    setPoints((prev) => prev.slice(0, prev.length - 1))
  }

  const handleFix = () => {
    setPoints((prev) => {
      if (prev.length === 0) {
        return []
      }
      return [...prev, { x: prev[0].x, y: prev[0].y }]
    })
  }
  return (
    <WithDraggable isShow={true} pos={{ x: 50, y: -1000 + 50 }}>
      <div className={`modal-pop-wrap ssm ${showOutlineModal ? 'mount' : ''} `}>
        <div className="modal-head">
          <h1 className="title">{getMessage('modal.cover.outline.drawing')}</h1>
          <button className="modal-close" onClick={() => setShowOutlineModal(false)}>
            닫기
          </button>
        </div>
        <div className="modal-body">
          <div className="modal-btn-wrap">
            <button
              className={`btn-frame modal ${type === OUTER_LINE_TYPE.OUTER_LINE ? 'act' : ''}`}
              onClick={() => setType(OUTER_LINE_TYPE.OUTER_LINE)}
            >
              {getMessage('modal.cover.outline')}
            </button>

            <button
              className={`btn-frame modal ${type === OUTER_LINE_TYPE.RIGHT_ANGLE ? 'act' : ''}`}
              onClick={() => setType(OUTER_LINE_TYPE.RIGHT_ANGLE)}
            >
              {getMessage('modal.cover.outline.right.angle')}
            </button>
            <button
              className={`btn-frame modal ${type === OUTER_LINE_TYPE.LEE_GUBAE ? 'act' : ''}`}
              onClick={() => setType(OUTER_LINE_TYPE.LEE_GUBAE)}
            >
              {getMessage('modal.cover.outline2')}
            </button>
            <button className={`btn-frame modal ${type === OUTER_LINE_TYPE.ANGLE ? 'act' : ''}`} onClick={() => setType(OUTER_LINE_TYPE.ANGLE)}>
              {getMessage('modal.cover.outline.angle')}
            </button>
            <button
              className={`btn-frame modal ${type === OUTER_LINE_TYPE.DIAGONAL_LINE ? 'act' : ''}`}
              onClick={() => setType(OUTER_LINE_TYPE.DIAGONAL_LINE)}
            >
              {getMessage('modal.cover.outline.diagonal')}
            </button>
          </div>
          <div className="modal-check-btn-wrap">
            <h3 className="check-wrap-title">{getMessage('modal.cover.outline.setting')}</h3>
            {type === OUTER_LINE_TYPE.OUTER_LINE ? (
              <div className="outer-line-wrap">
                <div className="form-input">
                  <label htmlFor="">{getMessage('modal.cover.outline.length')}</label>
                  <input
                    type="text"
                    className="input-origin block"
                    value={length1}
                    ref={length1Ref}
                    onChange={(e) => {
                      setLength1(e.target.value.replace(/[^-0-9]/g, ''))
                    }}
                    placeholder="3000"
                  />
                </div>
                <div className="form-input">
                  <label htmlFor="">{getMessage('modal.cover.outline.arrow')}</label>
                  <input type="text" value={arrow1} className="input-origin block" />
                </div>
              </div>
            ) : type === OUTER_LINE_TYPE.RIGHT_ANGLE ? (
              <div className="outer-line-wrap">
                <div className="form-input">
                  <label htmlFor="">{getMessage('modal.cover.outline.length')}</label>
                  <input
                    type="text"
                    className="input-origin block"
                    value={length1}
                    ref={length1Ref}
                    onChange={(e) => {
                      setLength1(e.target.value.replace(/[^-0-9]/g, ''))
                    }}
                    placeholder="3000"
                  />
                </div>
                <div className="form-input">
                  <label htmlFor="">{getMessage('modal.cover.outline.arrow')}</label>
                  <input type="text" value={arrow1} className="input-origin block" />
                </div>
                <div className="form-input">
                  <label htmlFor="">{getMessage('modal.cover.outline.length')}</label>
                  <input
                    type="text"
                    className="input-origin block"
                    value={length2}
                    ref={length2Ref}
                    onChange={(e) => {
                      setLength2(e.target.value.replace(/[^-0-9]/g, ''))
                    }}
                    placeholder="3000"
                  />
                </div>
                <div className="form-input">
                  <label htmlFor="">{getMessage('modal.cover.outline.arrow')}</label>
                  <input type="text" value={arrow2} className="input-origin block" />
                </div>
              </div>
            ) : (
              <></>
            )}
            <div className="flex-check-box for2 btn">
              <button className="arr-btn dark" onClick={handleFix}>
                <span>{getMessage('modal.cover.outline.fix')}</span>
              </button>
              <button className="arr-btn dark act" onClick={handleRollback}>
                <span>{getMessage('modal.cover.outline.rollback')}</span>
              </button>
              <button className="arr-btn dark">
                <span>{getMessage('modal.cover.outline.remove')}</span>
              </button>
              <button className="arr-btn dark">
                <span>{getMessage('modal.cover.outline.select.move')}</span>
              </button>
            </div>
          </div>
        </div>
      </div>
    </WithDraggable>
  )
}
