import PropTypes from '../_util/vue-types';
import { ConfigConsumerProps } from '../config-provider';
import BaseMixin from '../_util/BaseMixin';
import Pickr from '@simonwep/pickr/dist/pickr.es5.min';
import Icon from '../icon';
import LocaleReceiver from '../locale-provider/LocaleReceiver';
import enUS from './locale/en_US';
import debounce from 'lodash/debounce';

import { getOptionProps, findDOMNode } from '../_util/props-util';
let colors = '#194d33';
export default {
  name: 'AColorPicker',
  mixins: [BaseMixin],
  model: {
    prop: 'value',
    event: 'change.value', //为了支持v-model直接返回颜色字符串 所以用了自定义的事件,与pickr自带change事件进行区分
  },
  props: {
    prefixCls: PropTypes.string,
    defaultValue: PropTypes.string, //默认值
    config: PropTypes.object, //pickr配置
    value: PropTypes.string, //颜色值
    locale: PropTypes.object, //双语包
    colorRounded: PropTypes.number, //颜色数值保留几位小数
    size: PropTypes.oneOf(['default', 'small', 'large']).def('default'), //尺寸
    getPopupContainer: PropTypes.func, //指定渲染容器
    disabled: PropTypes.bool.def(false), //是否禁用
    format: PropTypes.string, //颜色格式设置
    alpha: PropTypes.bool.def(false), //是否开启透明通道
    hue: PropTypes.bool.def(true), //是否开启色彩预选
  },
  inject: {
    configProvider: { default: () => ConfigConsumerProps },
  },
  data() {
    return {
      colors,
      myOpen: false,
      pickr: null,
      i18n: enUS,
    };
  },
  watch: {
    'configProvider.locale.ColorPicker': {
      handler(val) {
        if (this.locale) return;
        this.i18n = val;
        this.reInitialize();
      },
    },
    locale(val) {
      this.i18n = val.ColorPicker || val.lang;
      this.reInitialize();
    },
    value(val) {
      this.setColor(val);
    },
    disabled(val) {
      this.pickr[val ? 'disable' : 'enable']();
    },
    config: {
      handler() {
        this.reInitialize();
      },
      deep: true,
    },
    format(val) {
      const type = val.toLocaleUpperCase();
      let res = this.pickr.setColorRepresentation(type);
      if (res) {
        this.pickr.applyColor();
      } else {
        throw new TypeError('format was invalid');
      }
    },
  },
  mounted() {
    if (this.locale) {
      this.i18n = this.locale.ColorPicker || this.locale.lang;
    }
    this.createPickr();
    this.eventsBinding();
  },
  destroyed() {
    this.pickr.destroyAndRemove();
  },
  methods: {
    reInitialize() {
      this.pickr.destroyAndRemove();
      const dom = document.createElement('div');
      dom.id = 'color-picker' + this._uid;
      const box = findDOMNode(this).querySelector('#color-picker-box' + this._uid);
      box.appendChild(dom);
      this.createPickr();
      this.eventsBinding();
    },
    setColor: debounce(function(val) {
      this.pickr.setColor(val);
    }, 1000),
    eventsBinding() {
      const pickrEvents = [
        'init',
        'hide',
        'show',
        'save',
        'clear',
        'change',
        'changestop',
        'cancel',
        'swatchselect',
      ];
      Object.keys(this.$listeners).forEach(event => {
        pickrEvents.includes(event) && this.pickr.on(event, this.$listeners[event]);
      });
    },
    createPickr() {
      const { getPopupContainer } = getOptionProps(this);
      const { getPopupContainer: getContextPopupContainer } = this.configProvider;
      const container = getPopupContainer || getContextPopupContainer;
      this.pickr = Pickr.create(
        Object.assign(
          {
            el: '#color-picker' + this._uid,
            container: (container && container(findDOMNode(this))) || document.body,
            theme: 'monolith', // or 'monolith', or 'nano'
            default: this.value || this.defaultValue || null, // 有默认颜色pickr才可以获取到_representation
            components: {
              // Main components
              preview: true,
              opacity: this.alpha,
              hue: this.hue,
              // Input / output Options
              interaction: {
                hex: true,
                rgba: true,
                input: true,
                clear: true,
                save: true,
              },
            },
          },
          this.config,
          { i18n: this.i18n },
        ),
      )
        .on('save', (color, instance) => {
          if (color) {
            let _representation = instance._representation || 'HEXA';
            color = color['to' + _representation]().toString(this.colorRounded || 0);
          }
          this.$emit('change.value', color || '');
        })
        .on('hide', () => {
          this.setState({ myOpen: false });
        });
    },
    handleOpenChange() {
      const open = !this.myOpen;
      this.setState({ myOpen: open });
      this.pickr[open ? 'show' : 'hide']();
      this.$emit('openChange', open);
    },
    getDefaultLocale() {
      const result = {
        ...enUS,
        ...this.$props.locale,
      };
      result.lang = {
        ...result.lang,
        ...(this.$props.locale || {}).lang,
      };
      return result;
    },
    renderColorPicker() {
      const { prefixCls: customizePrefixCls } = this.$props;
      const { getPrefixCls } = this.configProvider;
      const prefixCls = getPrefixCls('color-picker', customizePrefixCls);
      const { disabled } = getOptionProps(this);
      const classString = {
        [prefixCls]: true,
        [`${prefixCls}-open`]: this.myOpen,
        [`${prefixCls}-lg`]: this.size === 'large',
        [`${prefixCls}-sm`]: this.size === 'small',
        [`${prefixCls}-disabled`]: this.disabled,
      };
      return (
        <div class={classString} tabindex={disabled ? -1 : 0} onClick={this.handleOpenChange}>
          <div class={`${prefixCls}-selection`}>
            <div id={'color-picker-box' + this._uid}>
              <div id={'color-picker' + this._uid}></div>
            </div>
            <Icon type="down" class={`${prefixCls}-icon`} />
          </div>
        </div>
      );
    },
  },
  render() {
    return (
      <LocaleReceiver
        componentName="ColorPicker"
        defaultLocale={this.getDefaultLocale}
        scopedSlots={{ default: this.renderColorPicker }}
      />
    );
  },
};
