import React, { useEffect, useState, useCallback } from 'react';
import { useParams, useNavigate, useSearchParams } from 'react-router-dom';
import { useRecoilState } from 'recoil';
import {
  EasyTwinRenderer,
  EasyTwinLoader,
  treeList2SimpleList,
  ComponentInfo,
  Scene,
} from '@easytwin/core';
import { AllScreenModal } from '@/components';
import { _themeLoading } from '@/pages/module';
import { useProject } from '@/pages/ProjectManage/module';
import {
  _projectInfo,
  _componenterTreeList,
  ProjectEditorPageParams,
  useComponenter,
  _sceneId,
} from '@/pages/ProjectEditor/module';
import { useQuery } from 'react-query';
import { SceneApi } from '../../server';

const CONTAINER_ID = 'scene-preview';

export default function ProjectPreview() {
  const { projectId } = useParams<ProjectEditorPageParams>();
  const [searchParams] = useSearchParams();
  const navigate = useNavigate();
  const [, setThemeLoading] = useRecoilState(_themeLoading);

  const { getProjectInfo } = useProject();
  const [projectInfo, setProjectInfo] = useRecoilState(_projectInfo);
  const handleGetProjectInfo = useCallback(async () => {
    if (!projectId) return;
    const info = await getProjectInfo(projectId);
    if (info) {
      setProjectInfo(info);
    }
  }, [getProjectInfo, projectId, setProjectInfo]);

  useEffect(() => {
    handleGetProjectInfo();
  }, [handleGetProjectInfo]);

  /**
   * sceen
   */

  const [easyTwinRenderer, setEasyTwinRenderer] = useState<EasyTwinRenderer>();
  const [easyTwinLoader, setEasyTwinLoader] = useState<EasyTwinLoader>();
  const [sceenLoaded, setSceenLoaded] = useState(false);
  const [, setSceneId] = useRecoilState(_sceneId);

  const { data } = useQuery('sceneInfo', () => {
    if (projectId) {
      return SceneApi.getScene({ projectId });
    }
    throw Error('缺失 projectId');
  });

  const sceneInfo = data as Scene;

  useEffect(() => {
    if (sceneInfo?.id) {
      setSceneId(sceneInfo.id);
    }
  }, [sceneInfo?.id, setSceneId]);

  useEffect(() => {
    const containerDom = document.getElementById(CONTAINER_ID);
    if (containerDom !== null && !easyTwinRenderer && !easyTwinLoader) {
      const renderer = new EasyTwinRenderer({
        containerId: CONTAINER_ID,
      });
      renderer.setViewMode('preview');
      setEasyTwinRenderer(renderer);

      const loader = new EasyTwinLoader(renderer);
      setEasyTwinLoader(loader);
    }

    return () => {
      if (easyTwinRenderer) {
        easyTwinRenderer.disposeViewport();
        setEasyTwinRenderer(undefined);
      }
      if (easyTwinLoader) {
        setEasyTwinLoader(undefined);
      }
    };
  }, [easyTwinLoader, easyTwinRenderer]);

  /**
   * componenter
   */

  const { getComponenterTreeList } = useComponenter();
  const [componenterTreeList, setComponenterTreeList] = useRecoilState(_componenterTreeList);

  useEffect(() => {
    getComponenterTreeList();

    return () => {
      setComponenterTreeList(undefined);
    };
  }, [getComponenterTreeList, setComponenterTreeList]);

  useEffect(() => {
    if (componenterTreeList) {
      if (!componenterTreeList.length) setThemeLoading(false);
      else setThemeLoading(!sceenLoaded);
    } else {
      setThemeLoading(true);
    }
  }, [sceenLoaded, setThemeLoading, componenterTreeList]);

  useEffect(() => {
    const loadSceneConfig = async () => {
      if (sceneInfo && easyTwinLoader) {
        easyTwinLoader.initSceneConfig(sceneInfo);
      }
    };

    loadSceneConfig();
  }, [easyTwinLoader, sceneInfo]);

  useEffect(() => {
    const loadScene = async () => {
      if (easyTwinLoader && componenterTreeList) {
        await easyTwinLoader.initScene(treeList2SimpleList<ComponentInfo>(componenterTreeList));
        setSceenLoaded(true);
      }
    };

    loadScene();
  }, [easyTwinLoader, componenterTreeList]);

  return (
    <AllScreenModal title="预览" onClose={() => navigate(searchParams.get('from') || '/')}>
      <div id={CONTAINER_ID} className="h-full" />
    </AllScreenModal>
  );
}
