import React, { useContext } from "react";
import {
  EasyArea,
  EasyArray,
  EasyBoolean,
  EasyCamera,
  EasyCameras,
  EasyCheckbox,
  EasyColor,
  EasyColorControl,
  EasyColors,
  EasyComponents,
  EasyFolder,
  EasyFont,
  EasyGrid,
  EasyImgCard,
  EasyImgSize,
  EasyInput,
  EasyJscode,
  EasyJson,
  EasyMenu,
  EasyModel,
  EasyMulticolor,
  EasyNumber,
  EasyPages,
  EasyPanels,
  EasyPosition,
  EasyPositionConstraints,
  EasyPreviewAction,
  EasyRadio,
  EasyRange,
  EasyRangeColor,
  EasyRemoteEvent,
  EasySelect,
  EasySelectCard,
  EasyShadow,
  EasyText,
  EasyTextStyle,
  EasyTreeSelect,
  EasyUpload,
} from "../config-types";
import FormItem from "../layout/FormItem";
import { GuiContext } from "./context";

export default function Field(props) {
  const {
    type = "number",
    name,
    displayName,
    dependencies,
    value,
    config = {},
    path = [],
    tip,
    mode,
    bordered,
    style,
    onChange,
    onCustomEvents,
    customField,
  } = props;
  const { superStateList } = useContext(GuiContext);
  const handleChange = (value) => {
    onChange({
      path: path,
      value,
    });
  };

  const _onCustomEvents = (value) => {
    onCustomEvents &&
      onCustomEvents({
        path: path,
        value,
      });
  };

  const handleScopeChange = (scope) => {
    onChange({
      value: scope,
      path: path,
      field: "scope",
    });
  };

  const handleConfigChange = (newConfig) => {
    onChange({
      value: {
        ...config,
        ...newConfig,
      },
      path: path,
      field: "config",
    });
  };

  const handleColorsChange = (value, relativePath) =>
    onChange({ value: value, path: path.concat(relativePath) });

  if (type === "array") {
    return (
      <EasyArray
        name={name}
        bordered={bordered}
        path={path}
        displayName={displayName}
        value={value}
        tip={tip}
        template={config.template}
        defaultCollapsed={!config.defaultOpen}
        onChange={onChange}
        onCustomEvents={onCustomEvents}
      />
    );
  }

  if (type === "menu") {
    return (
      <EasyMenu path={path} config={config} onChange={onChange} onCustomEvents={onCustomEvents} />
    );
  }

  if (type === "remoteOptions") {
    return <EasyRemoteEvent value={value} onChange={handleChange} />;
  }

  if (type === "panelOptions") {
    return <EasyPanels value={value} onChange={handleChange} />;
  }

  const renderField = (type) => {
    switch (type) {
      case "text":
        return <EasyText value={value} />;
      case "input":
        return (
          <EasyInput
            placeholder={config.placeholder}
            disabled={config.disabled}
            prefix={config.prefix}
            suffix={config.suffix}
            value={value}
            onChange={handleChange}
          />
        );
      case "select": {
        const { api, placeholder, allowInput, options, localOptionsVar } = config;
        return (
          <EasySelect
            value={value}
            placeholder={placeholder}
            allowInput={allowInput}
            options={options}
            api={api}
            localOptionsVar={localOptionsVar}
            onChange={handleChange}
          />
        );
      }
      case "selectCard":
        return (
          <EasySelectCard
            value={value}
            placeholder={config.placeholder}
            allowInput={config.allowInput}
            options={config.options}
            onChange={handleChange}
          />
        );
      case "imgCard":
        return (
          <EasyImgCard
            dependencies={dependencies}
            options={config.options}
            api={config.api}
            openCache={config.openCache}
            onConfigChange={handleConfigChange}
            onChange={handleChange}
            value={value}
          />
        );
      case "treeSelect": {
        const { api, options, multiple, localOptionsVar } = config;

        return (
          <EasyTreeSelect
            api={api}
            value={value}
            options={options}
            multiple={multiple}
            localOptionsVar={localOptionsVar}
            onChange={handleChange}
          />
        );
      }
      case "area":
        return <EasyArea value={value} onChange={handleChange} />;
      case "componentOptions":
        return (
          <EasyComponents
            value={value}
            scope={config.scope}
            scopeOptions={config.scopeOptions}
            multiple={false}
            onChange={handleChange}
            onScopeChange={handleScopeChange}
          />
        );
      case "pageOptions":
        return <EasyPages value={value} onChange={handleChange} />;
      case "boolean":
        return (
          <EasyBoolean
            mode={config.mode}
            icon={config.icon}
            disabled={config.disabled}
            value={value}
            onChange={handleChange}
          />
        );
      case "radio":
        return (
          <EasyRadio
            value={value}
            mode={config.mode}
            direction={config.direction}
            options={config.options}
            onChange={handleChange}
          />
        );
      case "checkbox":
        return <EasyCheckbox value={value} options={config.options} onChange={handleChange} />;
      case "color":
        return (
          <EasyColor
            value={value}
            simple={config.simple}
            onChange={handleChange}
            unAlpha={config.unAlpha}
          />
        );
      case "colorControl":
        return (
          <EasyColorControl
            value={value}
            onChange={handleChange}
            name={name}
            displayName={displayName}
          />
        );
      case "multicolor":
        return <EasyMulticolor value={value} simple={config.simple} onChange={handleChange} />;
      case "colors":
        return <EasyColors value={value} onChange={handleColorsChange} unAlpha={config.unAlpha} />;
      case "range":
        return (
          <EasyRange
            value={value}
            min={config.min}
            max={config.max}
            step={config.step}
            suffix={config.suffix}
            onChange={handleChange}
          />
        );
      case "uploadImage":
      case "image":
      case "pointNineImage":
      case "video":
      case "uploadModel":
      case "audio":
      case "model":
      case "file":
        return (
          <EasyUpload
            type={type}
            maxSize={config.maxSize}
            value={value}
            onCustomEvents={onCustomEvents ? _onCustomEvents : onCustomEvents}
            onChange={handleChange}
            accept={config.accept}
            showDownload={true}
            customField={customField}
          />
        );
      case "folder":
        return <EasyFolder value={value} config={config} onChange={handleChange} />;
      case "position":
        return <EasyPosition value={value} onChange={handleChange} />;
      case "font":
        return <EasyFont value={value} onChange={handleChange} />;
      case "grid":
        return <EasyGrid value={value} options={config.options} onChange={handleChange} />;
      case "shadow":
        return <EasyShadow value={value} onChange={handleChange} unAlpha={config.unAlpha} />;
      case "textStyle":
        return <EasyTextStyle value={value} onChange={handleChange} unAlpha={config.unAlpha} />;
      case "camera":
        return (
          <EasyCamera
            name="镜头"
            value={value}
            template={config.template}
            enableDelete={false}
            onChange={handleChange}
          />
        );
      case "cameras":
        return (
          <EasyCameras
            value={value}
            template={config.template}
            min={config.min}
            onChange={handleChange}
          />
        );
      case "previewAction":
        return <EasyPreviewAction path={path} />;
      case "rangeColor":
        return <EasyRangeColor value={value} onChange={handleChange} />;
      case "json": {
        const { showGutter, ...otherConfig } = config;
        return (
          <EasyJson
            {...otherConfig}
            name={name}
            value={value}
            showGutter={showGutter}
            onChange={handleChange}
          />
        );
      }
      case "jscode": {
        const { showGutter, ...otherConfig } = config;
        return (
          <EasyJscode
            {...otherConfig}
            name={name}
            value={value}
            showGutter={showGutter}
            onChange={handleChange}
          />
        );
      }

      case "imgSize": {
        const { lock, showLabel = true } = config;
        return (
          <EasyImgSize
            value={value}
            onChange={onChange}
            path={path}
            lock={lock}
            showLabel={showLabel}
          />
        );
      }

      case "number":
        return (
          <EasyNumber
            label={mode === "vertical" && displayName}
            value={value}
            precision={config.precision}
            validataFun={config.validataFun}
            min={config.min}
            max={config.max}
            step={config.step}
            isEventMark={config.isEventMark}
            prefix={config.prefix}
            suffix={config.suffix}
            showStep={config.showStep}
            placeholder={config.placeholder}
            disabled={config.disabled}
            onChange={handleChange}
          />
        );

      // 万能子组件状态关联选择
      case "stateSelect":
        return (
          <EasySelect
            value={value}
            placeholder="请选择状态"
            options={superStateList}
            onChange={handleChange}
          />
        );
      case "positionConstraints":
        return <EasyPositionConstraints value={value} onChange={handleChange} />;
      default:
        return typeof value === "object" ? (
          <EasyJson
            name={name}
            value={value}
            showGutter={config.showGutter}
            onChange={handleChange}
          />
        ) : (
          <EasyInput
            placeholder={config.placeholder}
            disabled={config.disabled}
            prefix={config.prefix}
            suffix={config.suffix}
            value={value}
            onChange={handleChange}
          />
        );
    }
  };

  return (
    <FormItem
      label={mode === "vertical" && type === "number" ? "" : displayName}
      mode={mode}
      tip={tip}
      isEventMark={config.isEventMark}
      style={style}
      align={mode === "vertical" && type !== "range" ? "center" : "left"}
    >
      {renderField(type)}
    </FormItem>
  );
}
