import React, { FC, useContext, useState } from 'react';
import { SketchPicker } from 'react-color';

import { Box } from '@chakra-ui/react';
import Popover from '../popover';
import Input, { InputProps } from '../input';
import { ConfigContext } from '../config-provider';

export interface ColorPickerInputProps
  extends Omit<InputProps, 'suffix' | 'onChange' | 'value' | 'defaultValue'> {
  defaultValue?: string;
  value?: string;
  /** 输入的颜色符合颜色正确值才触发 */
  onChange?: (value: string) => void;
  /** 模式，色值模式或 rgb 模式，不设置时两种都支持 */
  mode?: 'hex' | 'rgb';
}

const hexReg = /(^#[\da-f]{6}$)|(^#[\da-f]{4}$)|(^#[\da-f]{3}$)/i;
const rgbReg = /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/;
const rgbaReg = /^rgba\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/;

const ColorPickerInput: FC<ColorPickerInputProps> = ({
  mode,
  value,
  defaultValue,
  onChange,
  onBlur,
  ...props
}) => {
  const { getPrefixCls } = useContext(ConfigContext);
  const [inputValue, setInputValue] = useState(() => defaultValue);

  // 外部设置 value 时，内部要同步
  React.useEffect(() => {
    if (value !== inputValue) {
      setInputValue(value);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [value]);

  return (
    <Input
      {...props}
      value={inputValue}
      onChange={e => {
        const val = e.target.value;
        setInputValue(val);
        if (onChange) {
          if (!val) {
            onChange(val);
            return;
          }
          if (mode === 'hex') {
            if (hexReg.test(val)) {
              onChange(val);
            }
          } else if (mode === 'rgb') {
            if (rgbReg.test(val) || rgbaReg.test(val)) {
              onChange(val);
            }
          } else if (hexReg.test(val) || rgbReg.test(val) || rgbaReg.test(val)) {
            onChange(val);
          }
        }
      }}
      onBlur={e => {
        const val = e.target.value;
        // 失焦时如果值不正确，设置成外部的 value
        if (val) {
          if (mode === 'hex') {
            if (!hexReg.test(val)) {
              setInputValue(value);
            }
          } else if (mode === 'rgb') {
            if (!rgbReg.test(val) && !rgbaReg.test(val)) {
              setInputValue(value);
            }
          } else if (!hexReg.test(val) && !rgbReg.test(val) && !rgbaReg.test(val)) {
            setInputValue(value);
          }
        }

        onBlur?.(e);
      }}
      suffix={
        <Popover
          placement="bottomRight"
          trigger="click"
          align={{ offset: [12, 8] }}
          overlayClassName={getPrefixCls('color-picker-input-popover-overlay')}
          content={
            <SketchPicker
              color={value || 'transparent'}
              onChange={colorState => {
                if (onChange) {
                  if (mode === 'hex') {
                    onChange(colorState.hex);
                    setInputValue(colorState.hex);
                  } else if (mode === 'rgb') {
                    const color = `rgba(${colorState.rgb.r},${colorState.rgb.g},${colorState.rgb.b},${colorState.rgb.a})`;
                    onChange(color);
                    setInputValue(color);
                  } else if (
                    colorState.source === 'hex' ||
                    colorState.source === 'hsv' ||
                    colorState.source === 'hsl'
                  ) {
                    onChange(colorState.hex);
                    setInputValue(colorState.hex);
                  } else if (colorState.source === 'rgb') {
                    const color = `rgba(${colorState.rgb.r},${colorState.rgb.g},${colorState.rgb.b},${colorState.rgb.a})`;
                    onChange(color);
                    setInputValue(color);
                  }
                }
              }}
            />
          }
        >
          <Box
            w="24px"
            h="24px"
            borderRadius="4px"
            boxShadow="inset 0 0 0 1px rgba(0, 0, 0, 0.07), inset 0 1px 3px 0 rgba(0, 0, 0, 0.15)"
            cursor="pointer"
            {...(inputValue
              ? { bg: inputValue }
              : {
                  bgPos: '0 0,4px 4px',
                  bgSize: '8px 8px',
                  bgImage:
                    'linear-gradient(45deg,#dfe3e8 25%,transparent 0,transparent 75%,#dfe3e8 0,#dfe3e8),linear-gradient(45deg,#dfe3e8 25%,#fff 0,#fff 75%,#dfe3e8 0,#dfe3e8)',
                })}
          />
        </Popover>
      }
    />
  );
};

export default ColorPickerInput;
