import React, { useCallback, useEffect, useRef } from "react";
import {
  getComponentDimension,
  getValueObjFromConfig,
  reduceConfig,
  transformConfig,
  updateArrayConfig,
} from "../_util/config";
import ComponentDimension from "../component-dimension";
import { EasyMenu } from "../config-types";
import { Tabs } from "../easy-design";
import { GuiContext } from "./context";
import Generate from "./Generate";
import Header from "./Header";

const basePath = ["chart", "dimension"];

export default function EasyGUI(props) {
  let {
    config: originConfig = [],
    flat = true,
    onChange,
    onFieldsChange,
    hideDefault,
    onHideDefaultChange,
    onCustomEvents,
    bordered = true,
    superStateList = [],
  } = props;
  const configRef = useRef(originConfig);

  useEffect(() => {
    configRef.current = originConfig;

    const handleCameraStateChange = ({ data }) => {
      const { type, status, value, path } = data;
      let event = new Event("updateState");
      if (type === "animation") {
        let value = transformConfig([
          getValueObjFromConfig(originConfig, path.slice(0, path.length - 1)),
        ]);
        let animationValue = reduceConfig(value[0].value);

        event.data = {
          type: "animation",
          value: {
            type: status,
            value: animationValue,
          },
        };
      } else if (type === "select") {
        event.data = {
          type: "camera",
          value: value,
        };
      }

      document.dispatchEvent(event);
    };

    document.addEventListener("collectCameraState", handleCameraStateChange, false);
    return () => {
      document.removeEventListener("collectCameraState", handleCameraStateChange);
    };
  }, [originConfig]);

  const handleChange = useCallback(
    async (updates) => {
      updates = Array.isArray(updates) ? updates : [updates];
      if (onChange) {
        let result = updateArrayConfig(configRef.current, updates);
        await onChange(result);
      }
      if (onFieldsChange) {
        await onFieldsChange(updates);
      }
    },
    [onChange, onFieldsChange, updateArrayConfig],
  );

  if (!Array.isArray(originConfig)) {
    console.error("config should be array");

    return <div>配置项格式错误</div>;
  }

  if (originConfig.length === 0) {
    return null;
  }

  // 转换配置，如果是旧配置项(以_开头)需要转化成新的(去掉_开头)
  let config = transformConfig(originConfig);

  let dimension;
  let positionConstraintsValue = undefined;

  // 优先展示组件的基本属性，将位置信息过滤
  config = config.reduce((result, current) => {
    if (current.name === "chart") {
      dimension = current.value.find((o) => o.name === "dimension");
      positionConstraintsValue = current.value.find(
        (o) => (o.name || o._name) === "positionConstraints",
      )?.value;
      if (dimension) {
        let withoutDimensionAndConstraintsConfig = current.value.filter(
          (o) => !["dimension", "positionConstraints"].includes(o.name || o._name),
        );
        if (withoutDimensionAndConstraintsConfig.length === 0) {
          return result;
        } else {
          return result.concat({
            ...current,
            value: withoutDimensionAndConstraintsConfig,
          });
        }
      } else {
        return result.concat(current);
      }
    } else if (current.name === "children") {
      // 过滤子组件配置
      return result;
    } else {
      return result.concat(current);
    }
  }, []);

  // 第一层级是都为横向的tab排列
  const isHorizontal = config.some((d) => d.config && d.config.layout === "horizontal");

  return (
    <div style={{ display: "contents" }} className="easyv-gui-component-wrapper">
      <GuiContext.Provider value={{ superStateList, guiTopConfig: originConfig }}>
        {dimension && (
          <ComponentDimension
            {...getComponentDimension(originConfig)}
            positionConstraints={positionConstraintsValue}
            path={basePath}
            onChange={handleChange}
            hideDefault={hideDefault}
            onHideDefaultChange={onHideDefaultChange}
          />
        )}

        {isHorizontal ? (
          <Tabs type="card" size="small">
            {config.map((d) => (
              <Tabs.TabPane key={d.name} tab={d.displayName}>
                {d.type === "menu" ? (
                  <EasyMenu
                    key={d.name}
                    config={d.value}
                    path={[d.name]}
                    onChange={handleChange}
                    onCustomEvents={onCustomEvents}
                  />
                ) : (
                  <Generate
                    onCustomEvents={onCustomEvents}
                    key={d.name}
                    config={d.value}
                    fullConfig={config}
                    path={[d.name]}
                    onChange={handleChange}
                    bordered={false}
                  />
                )}
              </Tabs.TabPane>
            ))}
          </Tabs>
        ) : flat &&
          config.every((d) => Array.isArray(d.value) && !(d.type && d.type !== "modal")) ? (
          config.map((d) => (
            <Generate
              key={d.name}
              bordered={bordered}
              path={[d.name]}
              fullConfig={config}
              onCustomEvents={onCustomEvents}
              config={d.value}
              onChange={handleChange}
            />
          ))
        ) : (
          <Generate
            bordered={bordered}
            fullConfig={config}
            config={config}
            onCustomEvents={onCustomEvents}
            onChange={handleChange}
          />
        )}
      </GuiContext.Provider>
    </div>
  );
}

export { Generate, Header };
