import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useState } from 'react';
import { Input } from '@easyv/react-gui';
import styles from './index.less';
import classNames from 'classnames';
import { ThemeConfigType, SeriesGradient, ThemeType, Type } from 'models/theme.types';
import { EasyPreviewColor } from '@easyv/react-gui';
import isNumber from 'lodash/isNumber';
import { transferColorToRgba } from 'utils/nodes';
import { defaultThememConfig } from 'constants/default-theme-config';

export enum ThemeConfigKey {
  TEXTCOLOR = 'textColor', // 文本色
  PALETTE = 'palette', // 纯色
  GRIDCOLOR = 'gridColor', // 网格色
  ASSISTCOLOR = 'assistColor', // 辅助色
  SERIESGRADIENT = 'seriesGradient' // 渐变色
}

type EditThemeType = {
  model: 'edit' | 'add';
  type: Type;
  onChange?: (config: ThemeConfigType) => void;
  curEditThemeConfig?: EditThemeConfigType;
};

type ThemeMark = {
  [x in keyof ThemeConfigType]?: number;
};

export type EditThemeRef = {
  themeConfig: EditThemeConfigType;
};
export const getInitthemeConfigByType: (type: Type) => EditThemeConfigType = (type) => {
  return {
    name: '未命名主题',
    config: defaultThememConfig,
    type
  };
};

let themeMark: ThemeMark = {};

export type EditThemeConfigType = Partial<Pick<ThemeType, 'id' | 'published' | 'updatedAt'>> &
  Omit<ThemeType, 'id' | 'published' | 'updatedAt'>;

const EditTheme = forwardRef<EditThemeRef, EditThemeType>((props, ref) => {
  const { model, onChange, type = Type.USER, curEditThemeConfig = getInitthemeConfigByType(Type.USER) } = props;

  const [configData, setConfigData] = useState<EditThemeConfigType>(model === 'add' ? getInitthemeConfigByType(type) : curEditThemeConfig!);

  useImperativeHandle(
    ref,
    () => ({
      themeConfig: configData
    }),
    [configData]
  );

  useEffect(() => {
    // 配置变化的时候才更新，其他不关注
    onChange?.(configData.config);
  }, [configData.config]);

  useEffect(() => {
    setConfigData(model === 'add' ? getInitthemeConfigByType(type) : curEditThemeConfig!);
  }, [model, type, props.curEditThemeConfig]);

  const [current, setCurrent] = useState<{ code: string; index?: number; targetRect?: any }>({
    code: '',
    index: -1
  });
  const isGradient = useMemo(() => {
    return current.code === 'seriesGradient';
  }, [current]);

  useEffect(() => {
    return () => {
      themeMark = {};
    };
  }, []);

  const handleClick = useCallback(
    ({ code, index = -1, event }: { code: string; index?: number; event: any }) => {
      if (configData.config[code]) {
        const targetRect = event.target.getBoundingClientRect();
        setTimeout(() => {
          //   先close ，再更新
          setCurrent({
            code,
            index,
            targetRect
          });
        }, 0);
      }
    },
    [configData]
  );

  const smartConfiguration = (data: ThemeConfigType, code: string): ThemeConfigType => {
    const _data = {
      ...data
    };
    // 智能联动规则
    const currentCodeMarkNumber = themeMark[code] || 0;
    if (code === ThemeConfigKey.TEXTCOLOR) {
      // 当【辅助信息色】【网格线色】未被修改时，修改【文本色】时【辅助信息色】【网格线色】根据以下规则联动更改
      if (!themeMark[ThemeConfigKey.GRIDCOLOR]) {
        // 网格色
        const color = transferColorToRgba(_data[code], 0.25);
        if (color) {
          _data[ThemeConfigKey.GRIDCOLOR] = color;
        }
      }
      if (!themeMark[ThemeConfigKey.ASSISTCOLOR]) {
        // 辅助色
        const color = transferColorToRgba(_data[code], 0.85);
        if (color) {
          _data[ThemeConfigKey.ASSISTCOLOR] = color;
        }
      }
    }

    if (code === ThemeConfigKey.PALETTE) {
      // 纯色
      if (!themeMark[ThemeConfigKey.SERIESGRADIENT]) {
        // 当【系列色-渐变】未被修改时，修改【系列-纯色】时【系列色-渐变】根据以下规则联动更改
        _data[ThemeConfigKey.SERIESGRADIENT] = _data[ThemeConfigKey.SERIESGRADIENT].map((d, i) => {
          const color = _data[ThemeConfigKey.PALETTE][i];
          const rgba = transferColorToRgba(color, 0) || color;
          return {
            ...d,
            gradient: [
              {
                color,
                offset: 0
              },
              {
                color: rgba,
                offset: 100
              }
            ]
          };
        });
      }
    }

    themeMark[code] = currentCodeMarkNumber + 1; // 做标记
    return _data;
  };

  const handleChange = useCallback(
    ({ code, value, index }: { code: string; value: string | SeriesGradient; index?: number }) => {
      let _theme = {
        ...configData.config
      };
      if (isNumber(index) && Array.isArray(configData.config[code])) {
        const _value = configData.config[code].map((d, i) => {
          if (i === index) {
            if (isGradient && Array.isArray(value) && value.length) {
              const firstItem = value[0];
              const lastItem = value[value.length - 1];
              const isFirstMax = firstItem.offset > lastItem.offset;
              return {
                angle: isFirstMax ? 0 : 180,
                gradient: value.sort((a, b) => a.offset - b.offset)
              };
            }
            return value;
          }
          return d;
        });
        _theme = {
          ..._theme,
          [code]: _value
        };
      } else {
        _theme = {
          ..._theme,
          [code]: value
        };
      }
      _theme = smartConfiguration(_theme, code);
      setConfigData({ ...configData, config: _theme });
    },
    [configData, isGradient]
  );

  const value = useMemo(() => {
    const _current = Array.isArray(configData.config[current.code])
      ? configData.config[current.code][current.index]
      : configData.config[current.code];
    if (isGradient && _current) {
      return _current.gradient;
    }
    return _current;
  }, [current, isGradient, configData]);

  return (
    <div className={styles.editTheme}>
      <span className={styles.customThemeName}>自定义主题</span>

      <div className={styles.editThemeName}>
        <Input
          maxLength={20}
          value={configData.name}
          placeholder="请输入主题名"
          onChange={(e) => {
            setConfigData({ ...configData, name: e.target.value.trim() });
          }}
        />
      </div>
      <div className={classNames(styles.themeColor)}>
        <span className={styles.name}>系列色-纯色</span>
        <ul className={styles.item}>
          {configData.config.palette.map((color, index) => (
            <span key={`${color}-${index}`}>
              <li
                style={{ backgroundColor: color }}
                className={current.code === 'palette' && current.index === index ? styles.current : ''}
                title={color}
                onClick={(event) => {
                  handleClick({
                    code: 'palette',
                    index,
                    event
                  });
                }}
              />
            </span>
          ))}
        </ul>
      </div>

      <div className={classNames(styles.themeColor)}>
        <span className={styles.name}>系列色-渐变色</span>
        <ul className={styles.item}>
          {configData.config.seriesGradient.map((item, index) => {
            const bgColor = `linear-gradient(${item.angle}deg, ${item.gradient.map((d) => `${d.color} ${d.offset}%`).join(', ')} )`;
            return (
              <li
                key={`${item.angle}-${index}`}
                style={{ background: bgColor }}
                className={current.code === 'seriesGradient' && current.index === index ? styles.current : ''}
                onClick={(event) => {
                  handleClick({
                    code: 'seriesGradient',
                    index,
                    event
                  });
                }}
              />
            );
          })}
        </ul>
      </div>

      <div className={classNames(styles.assistColor)}>
        <span className={styles.name}>辅助色</span>
        <ul className={styles.item}>
          <li
            data-name="文本色"
            onClick={(event) => {
              handleClick({
                code: 'textColor',
                event
              });
            }}>
            <div className={styles.color}>
              <span
                style={{
                  background: configData.config.textColor
                }}></span>
            </div>
          </li>
          <li
            data-name="辅助信息色"
            onClick={(event) => {
              handleClick({
                code: 'assistColor',
                event
              });
            }}>
            <div className={styles.color}>
              <span
                style={{
                  background: configData.config.assistColor
                }}></span>
            </div>
          </li>

          <li
            data-name="网格线色"
            onClick={(event) => {
              handleClick({
                code: 'gridColor',
                event
              });
            }}>
            <div className={styles.color}>
              <span
                style={{
                  background: configData.config.gridColor
                }}></span>
            </div>
          </li>
        </ul>
      </div>
      <div className={classNames(styles.themeColor, styles.bgColor)}>
        <span className={styles.name}>背景色</span>
        <ul className={styles.item}>
          <li
            onClick={(event) => {
              handleClick({
                code: 'bgColor',
                event
              });
            }}
            style={{
              background: configData.config.bgColor
            }}></li>
        </ul>
      </div>
      {value && (
        <EasyPreviewColor
          value={value}
          isGradient={isGradient}
          show={current.code && configData.config[current.code]}
          onHide={() => {
            setCurrent({
              code: '',
              index: -1
            });
          }}
          targetRect={current.targetRect}
          onChange={(value) => {
            handleChange({
              value,
              code: current.code,
              index: current.index
            });
          }}
        />
      )}
    </div>
  );
});
export default EditTheme;
