import React from 'react';
import { ExpandOutlined } from '@easyv/react-icons';
import { useRecoilState } from 'recoil';
import {
  StateTypeEnum,
  ViewpointTypeEnum,
  UpdateViewpointQuery,
  SceneConfig,
} from '@easytwin/core';
import { useProject } from '@/pages/ProjectManage/module';
import {
  _projectInfo,
  _sceneStateList,
  _sceneStatesSelectKey,
  _sceneViewpointList,
  _sceneViewpointSelectKey,
  _sceneId,
  _currentScene,
  useProjectEditerState,
  useProjectEditerViewpoint,
  useProjectEditerScene,
  ProjectEditorPageParams,
} from '@/pages/ProjectEditor/module';
import { useParams } from 'react-router-dom';
import { StateManage, ViewpointManage } from '..';
import { BaseForm } from './_components';

export default function SceneConfigForm() {
  const { projectId } = useParams<ProjectEditorPageParams>();

  if (!projectId) return null;

  const [projectInfo, setProjectInfo] = useRecoilState(_projectInfo);
  const { getProjectInfo: getSceneInfo } = useProject();

  const [currentScene] = useRecoilState(_currentScene);

  /**
   * scene
   */
  const [sceneId] = useRecoilState(_sceneId);
  const { updateScene } = useProjectEditerScene();

  const handleUpdateProjectInfo = React.useCallback(
    async (values: SceneConfig) => {
      if (!sceneId) return;
      const {
        description,
        thumb,
        useGroundImg,
        groundImgUrl,
        minLng,
        minLat,
        maxLng,
        maxLat,
        near,
        far,
      } = values;

      await updateScene({
        projectId,
        sceneId,
        commonConfig: {
          config: {
            description,
            thumb,
            useGroundImg,
            groundImgUrl,
            minLng,
            minLat,
            maxLng,
            maxLat,
            near,
            far,
          },
        },
      });

      const info = await getSceneInfo(projectId);
      info && setProjectInfo(info);
    },
    [projectId, sceneId, updateScene, getSceneInfo, setProjectInfo],
  );

  /**
   * state
   */

  const { createState, updateState, removeState } = useProjectEditerState();

  const [stateList] = useRecoilState(_sceneStateList);
  const [stateSelectKey, setStateSelectKey] = useRecoilState(_sceneStatesSelectKey);

  const handleAddState = React.useCallback(async () => {
    sceneId &&
      (await createState({
        bizId: sceneId,
        type: StateTypeEnum.PROJECT,
      }));
  }, [createState, sceneId]);

  /**
   * viewpoint
   */

  const { createViewpoint, updateViewpoint, removeViewpoint } = useProjectEditerViewpoint();

  const [viewpointList] = useRecoilState(_sceneViewpointList);
  const [viewpointSelectKey, setViewpointSelectKey] = useRecoilState(_sceneViewpointSelectKey);

  const handleCreateViewpoint = React.useCallback(async () => {
    if (sceneId && currentScene) {
      await createViewpoint({
        bizId: sceneId,
        type: ViewpointTypeEnum.PROJECT,
        config: currentScene.getCameraState(),
        rank: 0,
      });
    }
  }, [currentScene, createViewpoint, sceneId]);

  const handleUpdateViewpoint = React.useCallback(
    async (state: Partial<UpdateViewpointQuery>) => {
      if (projectInfo && currentScene) {
        const { id, bizId, ...rest } = state;
        if (id && bizId) {
          await updateViewpoint(
            {
              ...rest,
              id,
              bizId,
              config: currentScene.getCameraState(),
            },
            !state.name,
          );
        }
      }
    },
    [projectInfo, currentScene, updateViewpoint],
  );

  const scene = projectInfo?.scenes[0];

  return sceneId ? (
    <div className="h-full flex flex-col">
      {/* title */}
      <div className="p-3 text-white inline-flex items-center gap-x-2 border-b border-b-1 border-borderColorBase">
        <ExpandOutlined className="anticon text-primary text-base" />
        <span>场景配置</span>
      </div>

      <div className="flex-auto overflow-y-auto py-2">
        {scene && (
          <BaseForm scene={scene.commonConfig.config} onValuesChange={handleUpdateProjectInfo} />
        )}

        {/* state */}
        <StateManage
          type={StateTypeEnum.PROJECT}
          isGroup={false}
          dataSource={stateList}
          selectKey={stateSelectKey}
          onTabChange={setStateSelectKey}
          onAdd={handleAddState}
          onUpdate={(config) =>
            config.id &&
            updateState({
              ...config,
              bizId: sceneId,
              type: StateTypeEnum.PROJECT,
              id: config.id,
            })
          }
          onRemove={(id) => removeState({ bizId: sceneId, type: StateTypeEnum.PROJECT, id })}
        />

        {/* viewpoint */}
        <ViewpointManage
          dataSource={viewpointList}
          selectKey={viewpointSelectKey}
          onTabChange={setViewpointSelectKey}
          onFlyTo={() => {
            const old = viewpointSelectKey;
            setViewpointSelectKey(undefined);
            setTimeout(() => setViewpointSelectKey(old), 0);
          }}
          onAdd={handleCreateViewpoint}
          onUpdate={(config) =>
            handleUpdateViewpoint({
              ...config,
              bizId: sceneId,
              type: ViewpointTypeEnum.PROJECT,
              id: config.id,
            })
          }
          onRemove={(id) =>
            removeViewpoint({ id, bizId: sceneId, type: ViewpointTypeEnum.PROJECT })
          }
        />
      </div>
    </div>
  ) : null;
}
