import React, { Fragment, useContext, useState } from 'react';
import { Button, Tooltip } from '@easyv/antd';
import EasyGUI, {
  Icon,
  EasySelect,
  EasyNumber,
  EasyBoolean,
  EasyComponents,
  EasyGrid,
  Utils,
  FormItem,
  FormGroup,
  EasyRange,
  EasyJscode
} from '@easyv/react-gui';
import cloneDeep from 'lodash/cloneDeep';
import set from 'lodash/set';
import defaultActions from 'constants/default-actions';
import { isComponent, isGroup, isGeneralPanel, isPanel, isRefScreen } from 'utils/utils';
import { getId } from 'utils/interaction';
import ComponentConfig from './ComponentConfig';
import { ComponentContext, PanelContext, ScreenContext } from '../../../Context';
import DataTooltipModal from './DataTooltipModal';

const { updateArrayWithObject, reduceConfig } = Utils;

const animationTypes = [
  { name: '渐隐渐现', value: 'opacity' },
  { name: '向左移动', value: 'slideLeft' },
  { name: '向右移动', value: 'slideRight' },
  { name: '向上移动', value: 'slideUp' },
  { name: '向下移动', value: 'slideDown' }
];

const timingFunctions = [
  { name: '匀速', value: 'linear' },
  { name: '慢快慢', value: 'ease' },
  { name: '慢速开始', value: 'ease-in' },
  { name: '慢速结束', value: 'ease-out' },
  { name: '慢速开始和结束', value: 'ease-in-out' }
];

const groupActionExclude = ['updateConfig', 'switchState'];
const panelActionExclude = ['updateConfig'];
const componentActionExclude = ['switchState'];
const componentChildActionExclude = ['scale', 'translate', 'rotate', 'switchState'];

export default function ActionConfig({ value, tooltipData, onChange }) {
  const [componentConfigVisible, setComponentConfigVisible] = useState(false);
  const {
    component,
    componentScope,
    componentConfig,
    action,
    actionData,
    actionDataFn = 'return data;',
    scale = {},
    translate = {},
    rotate = {},
    stateId,
    unmount,
    animation
  } = value;
  const { x: scaleX = 1, y: scaleY = 1, lock: scaleLock = true, origin: scaleOrigin = '50% 50%' } = scale;
  const { toX: translateToX = 0, toY: translateToY = 0 } = translate;
  const { rotateX = 0, rotateY = 0, rotateZ = 0, perspective = false } = rotate;
  const { componentsById } = useContext(ComponentContext);
  const { panelsById } = useContext(PanelContext);
  const { screens = [], screensById } = useContext(ScreenContext);

  const filterActions = ({ actions, component }) => {
    if (component.length > 1) {
      return actions.filter((d) => !groupActionExclude.includes(d.value));
    } else {
      if (component.length === 1) {
        component = component[0];
      }

      if (isGroup(component)) {
        return actions.filter((d) => !groupActionExclude.includes(d.value));
      } else if (isGeneralPanel(component)) {
        return actions.filter((d) => !panelActionExclude.includes(d.value));
      } else if (isComponent(component)) {
        const componentInfo = componentsById[getId(component) as number];
        if (componentInfo && componentInfo.parent) {
          return actions.filter((d) => !componentChildActionExclude.includes(d.value));
        } else {
          return actions.filter((d) => !componentActionExclude.includes(d.value));
        }
      } else {
        return actions;
      }
    }
  };

  const getActions = () => {
    let actions = [];
    if (component.length === 1) {
      if (isComponent(component[0])) {
        const componentInfo = componentsById[getId(component[0]) as number];
        if (componentInfo) {
          actions = componentInfo.actions;
        }
      }
    }

    return actions;
  };

  const getStates = () => {
    let states = [];
    if (component.length === 1 && isGeneralPanel(component[0]) && action === 'switchState') {
      const panel = panelsById[getId(getId(component[0]) as string) as number];
      const screenId = getId(component[0]) + ''; // “” => number 不能进下面的正则判断 isPanel/isRefScreen
      if (panel) {
        states = panel.states
          .filter((d) => d)
          .map((d) => {
            let name, id;
            if (isPanel(screenId)) {
              const state = screensById[d];
              name = state?.name;
              id = state?.id;
            }
            if (isRefScreen(screenId)) {
              const state = screens.find((v) => v.screenId === d);
              name = state?.screenName;
              id = state?.screenId;
            }
            if (id && name) {
              return {
                name,
                value: `$state(${id})`
              };
            }

            return {
              name: `${d}（该屏已被删除）`,
              value: `$state(${d})`,
              disabled: true
            };
          });
      }
    }

    return states;
  };

  const handleConfigUpdate = (updates) => {
    updates = Array.isArray(updates) ? updates : [updates];
    const clonedActionData = cloneDeep(actionData || {});
    const newActionsData = updates.reduce((result, item) => {
      const { path, value } = item;
      return set(result, path, value);
    }, clonedActionData);

    onChange({
      paths: [],
      value: newActionsData,
      key: 'actionData'
    });
  };

  const actionOptions = defaultActions.concat(getActions());
  const currentAction = actionOptions.find((d) => d.value === action);
  const actionConfig = currentAction && currentAction.config;
  const useFnConfig = currentAction && currentAction.useFnConfig;
  const enable = component.length > 0;
  const hasChildComponent = component.some((d) => componentsById[getId(d) as number]?.parent);

  return (
    <>
      <FormItem label="组件">
        <EasyComponents
          value={component ? component : undefined}
          scope={componentScope}
          onChange={(component) => {
            const updated = [{ paths: [], value: component, key: 'component' }];

            if (componentConfig) {
              updated.push({ paths: [], value: {}, key: 'componentConfig' });
            }

            if (!['show', 'hide', 'show/hide', ''].includes(action)) {
              updated.push({ paths: [], value: '', key: 'action' });
            }

            if (stateId) {
              updated.push({ paths: [], value: '', key: 'state' });
            }

            onChange(updated);
          }}
          onScopeChange={(scope) => {
            if (scope === 'current') {
              onChange([
                { paths: [], value: [], key: 'component' },
                { paths: [], value: {}, key: 'componentConfig' },
                { paths: [], value: '', key: 'state' },
                { paths: [], value: scope, key: 'componentScope' }
              ]);
            } else {
              onChange({ paths: [], value: scope, key: 'componentScope' });
            }
          }}
        />
      </FormItem>

      {enable && (
        <FormItem label="动作">
          <EasySelect
            options={filterActions({ actions: actionOptions, component: component })}
            value={action}
            onChange={(value) => {
              const shouldUpdatedValues = [{ paths: [], value, key: 'action' }];

              if (!defaultActions.find((o) => o.value === value)) {
                // 自定义动作
                const defaultValue = reduceConfig(actionOptions.find((o) => o.value === value)?.config || []);
                shouldUpdatedValues.push({ paths: [], value: defaultValue, key: 'actionData' });
              }
              onChange(shouldUpdatedValues);
            }}
          />
        </FormItem>
      )}

      {actionConfig ? (
        <EasyGUI
          config={updateArrayWithObject(actionConfig, actionData)}
          path={[]}
          onFieldsChange={(params) => handleConfigUpdate(params)}
        />
      ) : null}

      {useFnConfig && (
        <FormItem label="参数" tip={`该动作所需要接收的数据：${useFnConfig.desc || ''}`}>
          <div>
            function emitData(
            <Tooltip title="数据">
              <span>data</span>
            </Tooltip>
            {') {'}
          </div>
          <EasyJscode
            value={actionDataFn}
            onChange={(value) => {
              onChange({ paths: [], value, key: 'actionDataFn' });
            }}
          />
          <div>{'}'}</div>
          {currentAction?.type && (
            <DataTooltipModal inData={tooltipData} outData={currentAction}>
              <Button type="primary">查看数据参考</Button>
            </DataTooltipModal>
          )}
        </FormItem>
      )}

      {action === 'updateConfig' && component && (
        <FormItem>
          <Button type="primary" ghost onClick={() => setComponentConfigVisible(true)}>
            编辑组件配置
          </Button>
        </FormItem>
      )}

      {action === 'switchState' && (
        <FormItem label="状态">
          <EasySelect
            options={getStates()}
            value={stateId}
            onChange={(value) => {
              onChange({ paths: [], value, key: 'stateId' });
            }}
          />
        </FormItem>
      )}

      {action === 'translate' && (
        <Fragment>
          <FormItem label="移动后位置">
            <FormGroup>
              <FormGroup.Col span={12}>
                <EasyNumber
                  suffix="X"
                  value={translateToX}
                  onChange={(value) => onChange({ paths: ['translate'], value: value, key: 'toX' })}
                />
              </FormGroup.Col>
              <FormGroup.Col span={12}>
                <EasyNumber
                  suffix="Y"
                  value={translateToY}
                  onChange={(value) => onChange({ paths: ['translate'], value: value, key: 'toY' })}
                />
              </FormGroup.Col>
            </FormGroup>
          </FormItem>
        </Fragment>
      )}

      {action === 'scale' && (
        <Fragment>
          <FormItem label="缩放原点">
            <EasyGrid
              options={['0% 0%', '50% 0%', '100% 0%', '0% 50%', '50% 50%', '100% 50%', '0% 100%', '50% 100%', '100% 100%']}
              value={scaleOrigin}
              onChange={(value) => onChange({ paths: ['scale'], value: value, key: 'origin' })}
            />
          </FormItem>
          <FormItem label="缩放比例">
            <FormGroup>
              <FormGroup.Col span={11}>
                <EasyNumber
                  suffix="%"
                  label="X"
                  min={0}
                  value={Math.round(scaleX * 100)}
                  onChange={(value) => {
                    let ratio = scaleX / scaleY;
                    ratio = isNaN(ratio) || ratio === Infinity ? 1 : ratio;
                    onChange([
                      { paths: ['scale'], value: value / 100, key: 'x' },
                      { paths: ['scale'], value: scaleLock ? value / 100 / ratio : scaleY, key: 'y' }
                    ]);
                  }}
                />
              </FormGroup.Col>
              <FormGroup.Col span={2} style={{ textAlign: 'center' }}>
                <Icon
                  type={scaleLock ? 'lock_on' : 'lock_off'}
                  style={{ fontSize: 20, marginLeft: -6, cursor: 'pointer' }}
                  onClick={() => onChange({ paths: ['scale'], value: !scaleLock, key: 'lock' })}
                />
              </FormGroup.Col>
              <FormGroup.Col span={11}>
                <EasyNumber
                  suffix="%"
                  label="Y"
                  min={0}
                  value={Math.round(scaleY * 100)}
                  onChange={(value) => {
                    let ratio = scaleX / scaleY;
                    ratio = isNaN(ratio) || ratio === Infinity ? 1 : ratio;

                    onChange([
                      { paths: ['scale'], value: value / 100, key: 'y' },
                      { paths: ['scale'], value: scaleLock ? ratio * (value / 100) : scaleX, key: 'x' }
                    ]);
                  }}
                />
              </FormGroup.Col>
            </FormGroup>
          </FormItem>
        </Fragment>
      )}

      {action === 'rotate' && (
        <Fragment>
          <FormItem label="旋转">
            <FormGroup>
              <FormGroup.Col span={24}>
                <FormItem mode="vertical" label="绕X轴" align="left" style={{ padding: 0 }}>
                  <EasyRange
                    value={rotateX}
                    min={-180}
                    max={180}
                    onChange={(value) => onChange({ paths: ['rotate'], value: value, key: 'rotateX' })}
                    suffix="°"
                  />
                </FormItem>
              </FormGroup.Col>
              <FormGroup.Col span={24}>
                <FormItem mode="vertical" label="绕Y轴" align="left" style={{ padding: 0 }}>
                  <EasyRange
                    value={rotateY}
                    min={-180}
                    max={180}
                    onChange={(value) => onChange({ paths: ['rotate'], value: value, key: 'rotateY' })}
                    suffix="°"
                  />
                </FormItem>
              </FormGroup.Col>
              <FormGroup.Col span={24}>
                <FormItem mode="vertical" label="绕Z轴" align="left" style={{ padding: 0 }}>
                  <EasyRange
                    value={rotateZ}
                    min={-180}
                    max={180}
                    onChange={(value) => onChange({ paths: ['rotate'], value: value, key: 'rotateZ' })}
                    suffix="°"
                  />
                </FormItem>
              </FormGroup.Col>
            </FormGroup>
          </FormItem>
          <FormItem label="透视">
            <EasyBoolean value={perspective} onChange={(checked) => onChange({ paths: ['rotate'], value: checked, key: 'perspective' })} />
          </FormItem>
        </Fragment>
      )}

      {enable && !hasChildComponent && ['show', 'hide', 'show/hide'].includes(action) && (
        <FormItem label="动画类型">
          <EasySelect
            options={animationTypes}
            value={animation.type}
            onChange={(value) => onChange({ paths: ['animation'], value, key: 'type' })}
          />
        </FormItem>
      )}

      {enable && !hasChildComponent && ['show', 'hide', 'show/hide', 'switchState', 'translate', 'scale', 'rotate'].includes(action) && (
        <FormItem label="速率">
          <EasySelect
            options={timingFunctions}
            value={animation.timingFunction || 'linear'}
            onChange={(value) => onChange({ paths: ['animation'], value, key: 'timingFunction' })}
          />
        </FormItem>
      )}

      {enable && !hasChildComponent && ['show', 'hide', 'show/hide', 'switchState', 'translate', 'scale', 'rotate'].includes(action) && (
        <FormItem label="动画时长">
          <EasyNumber value={animation.duration} onChange={(value) => onChange({ paths: ['animation'], value, key: 'duration' })} />
        </FormItem>
      )}

      {enable && (
        <FormItem label="延时(ms)">
          <EasyNumber value={animation.delay || 0} onChange={(value) => onChange({ paths: ['animation'], value, key: 'delay' })} />
        </FormItem>
      )}

      {enable && !hasChildComponent && ['show', 'hide', 'show/hide', 'switchState'].includes(action) && (
        <FormItem label="隐藏卸载">
          <EasyBoolean value={unmount} onChange={(checked) => onChange({ paths: [], value: checked, key: 'unmount' })} />
        </FormItem>
      )}

      <ComponentConfig
        id={component}
        config={componentConfig}
        visible={componentConfigVisible}
        onClose={() => setComponentConfigVisible(false)}
        onChange={onChange}
      />
    </>
  );
}
