'use client'

import { useContext, useEffect, useRef } from 'react'

import { useRecoilValue, useResetRecoilState } from 'recoil'

import QContextMenu from '@/components/common/context-menu/QContextMenu'
import PanelBatchStatistics from '@/components/floor-plan/modal/panelBatch/PanelBatchStatistics'
import ImgLoad from '@/components/floor-plan/modal/ImgLoad'
import { useCanvas } from '@/hooks/useCanvas'
import { usePlan } from '@/hooks/usePlan'
import { useContextMenu } from '@/hooks/useContextMenu'
import { useCanvasConfigInitialize } from '@/hooks/common/useCanvasConfigInitialize'
import { currentMenuState } from '@/store/canvasAtom'
import { totalDisplaySelector } from '@/store/settingAtom'
import { POLYGON_TYPE } from '@/common/common'
import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider'
import { QcastContext } from '@/app/QcastProvider'
import {
  makersState,
  modelsState,
  moduleStatisticsState,
  pcsCheckState,
  selectedMakerState,
  selectedModelsState,
  seriesState,
} from '@/store/circuitTrestleAtom'
import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
import { useEvent } from '@/hooks/useEvent'
import { compasDegAtom } from '@/store/orientationAtom'
import { hotkeyStore } from '@/store/hotkeyAtom'
import { usePopup } from '@/hooks/usePopup'

export default function CanvasFrame() {
  const canvasRef = useRef(null)
  const { canvas } = useCanvas('canvas')
  const { canvasLoadInit, gridInit } = useCanvasConfigInitialize()
  const { closeAll } = usePopup()
  const currentMenu = useRecoilValue(currentMenuState)
  const { floorPlanState } = useContext(FloorPlanContext)
  const { contextMenu, handleClick } = useContextMenu()
  const { plans, currentCanvasPlan, resetCanvasStatus } = usePlan()
  const totalDisplay = useRecoilValue(totalDisplaySelector) // 집계표 표시 여부
  const { setIsGlobalLoading } = useContext(QcastContext)
  const resetModuleStatisticsState = useResetRecoilState(moduleStatisticsState)
  const resetMakersState = useResetRecoilState(makersState)
  const resetSelectedMakerState = useResetRecoilState(selectedMakerState)
  const resetSeriesState = useResetRecoilState(seriesState)
  const resetModelsState = useResetRecoilState(modelsState)
  const resetCompasDeg = useResetRecoilState(compasDegAtom)
  const resetSelectedModelsState = useResetRecoilState(selectedModelsState)
  const resetPcsCheckState = useResetRecoilState(pcsCheckState)
  const { handleModuleSelectionTotal } = useCanvasPopupStatusController()
  const { basicSetting, fetchBasicSettings } = useCanvasSetting()
  const { selectedMenu, setSelectedMenu } = useCanvasMenu()
  const { initEvent } = useEvent()
  const loadCanvas = () => {
    if (!canvas) return

    canvas?.clear() // 캔버스를 초기화합니다.
    if (currentCanvasPlan) {
      const plan = plans.find((plan) => plan.id === currentCanvasPlan.id)
      if (plan?.canvasStatus && floorPlanState.objectNo === currentCanvasPlan.objectNo) {
        canvas?.loadFromJSON(JSON.parse(plan.canvasStatus), function () {
          canvasLoadInit() //config된 상태로 캔버스 객체를 그린다
          canvas?.renderAll() // 캔버스를 다시 그립니다.

          if (canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE).length > 0) {
            setTimeout(() => {
              setSelectedMenu('module')
            }, 500)
          } else if (canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL).length > 0) {
            setSelectedMenu('outline')
          } else {
            setTimeout(() => {
              setSelectedMenu('surface')
            }, 500)
          }

          const roofs = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)

          roofs.forEach((roof) => {
            const auxiliaryLines = canvas
              .getObjects()
              .filter((obj) => obj.name === 'auxiliaryLine' && roof.inPolygonImproved(obj.startPoint) && roof.inPolygonImproved(obj.endPoint))

            auxiliaryLines.forEach((auxiliaryLine) => {
              roof.innerLines.push(auxiliaryLine)
            })
          })

          initEvent()
        })
      } else {
        setSelectedMenu(null)
      }
      Object.keys(currentCanvasPlan).length > 0 && canvas && handleModuleSelectionTotal()
    } else {
      setSelectedMenu(null)
    }
    gridInit()
  }

  useEffect(() => {
    loadCanvas()
    resetRecoilData()

    /* 플랜번호가 있으면 베이직세팅 팝업 데이터 로드 */
    if (currentCanvasPlan.planNo) {
      /* 약간의 지연을 줘서 roofMaterials가 로드될 시간을 확보 */
      setTimeout(() => {
        fetchBasicSettings(Number(currentCanvasPlan.planNo), null)
      }, 100)
    }
  }, [currentCanvasPlan, canvas])

  useEffect(() => {
    setIsGlobalLoading(false)
    // 혹시 모를 팝업이 떠있는 경우 닫고 시작한다.
    closeAll()

    return () => {
      canvas?.clear()
      resetCanvasStatus()
    }
  }, [])

  const resetRecoilData = () => {
    // resetModuleStatisticsState()
    resetMakersState()
    resetSelectedMakerState()
    resetSeriesState()
    resetModelsState()
    resetCompasDeg()
    resetSelectedModelsState()
    resetPcsCheckState()
  }

  /**
   * 캔버스가 있을 경우 핫키 이벤트 처리
   * hotkeyStore에 핫키 이벤트 리스너 추가
   *
   * const hotkeys = [
   { key: 'c', fn: () => asdf() },
   { key: 'v', fn: () => qwer() },
   ]
   setHotkeyStore(hotkeys)
   */
  const hotkeyState = useRecoilValue(hotkeyStore)
  const hotkeyHandlerRef = useRef(null)

  useEffect(() => {
    hotkeyHandlerRef.current = (e) => {
      hotkeyState.forEach((hotkey) => {
        if (e.key === hotkey.key) {
          hotkey.fn()
        }
      })
    }

    document.addEventListener('keyup', hotkeyHandlerRef.current)

    return () => {
      if (hotkeyHandlerRef.current) {
        document.removeEventListener('keyup', hotkeyHandlerRef.current)
      }
    }
  }, [hotkeyState])
  /** 핫키 이벤트 처리 끝 */

  return (
    <div className="canvas-frame">
      <canvas ref={canvasRef} id="canvas" style={{ position: 'relative' }}></canvas>

      <QContextMenu contextRef={canvasRef} canvasProps={canvas}>
        {contextMenu?.map((menus, index) => (
          <ul key={index}>
            {menus.map((menu) => (
              <li key={menu.id} onClick={(e) => handleClick(e, menu)}>
                {menu.name}
              </li>
            ))}
          </ul>
        ))}
      </QContextMenu>
      {selectedMenu === 'module' && totalDisplay && <PanelBatchStatistics />}
      {/* 이미지 로드 팝업 */}
      <ImgLoad />
    </div>
  )
}
