import moment from 'moment';
import classNames from 'classnames';
import PropTypes from '../_util/vue-types';
import BaseMixin from '../_util/BaseMixin';
import Header from './Header';
import Combobox from './Combobox';
import { getComponent } from '../_util/props-util';

function noop() {}

function generateOptions(length, disabledOptions, hideDisabledOptions, step = 1) {
  const arr = [];
  for (let value = 0; value < length; value += step) {
    if (!disabledOptions || disabledOptions.indexOf(value) < 0 || !hideDisabledOptions) {
      arr.push(value);
    }
  }
  return arr;
}

function toNearestValidTime(time, hourOptions, minuteOptions, secondOptions) {
  const hour = hourOptions
    .slice()
    .sort((a, b) => Math.abs(time.hour() - a) - Math.abs(time.hour() - b))[0];
  const minute = minuteOptions
    .slice()
    .sort((a, b) => Math.abs(time.minute() - a) - Math.abs(time.minute() - b))[0];
  const second = secondOptions
    .slice()
    .sort((a, b) => Math.abs(time.second() - a) - Math.abs(time.second() - b))[0];
  return moment(`${hour}:${minute}:${second}`, 'HH:mm:ss');
}

const Panel = {
  name: 'Panel',
  inheritAttrs: false,
  mixins: [BaseMixin],
  props: {
    clearText: PropTypes.string,
    prefixCls: PropTypes.string.def('rc-time-picker-panel'),
    defaultOpenValue: {
      type: Object,
      default: () => {
        return moment();
      },
    },
    value: PropTypes.any,
    defaultValue: PropTypes.any,
    placeholder: PropTypes.string,
    format: PropTypes.string,
    inputReadOnly: PropTypes.bool.def(false),
    disabledHours: PropTypes.func.def(noop),
    disabledMinutes: PropTypes.func.def(noop),
    disabledSeconds: PropTypes.func.def(noop),
    hideDisabledOptions: PropTypes.bool,
    // onChange: PropTypes.func,
    // onEsc: PropTypes.func,
    allowEmpty: PropTypes.bool,
    showHour: PropTypes.bool,
    showMinute: PropTypes.bool,
    showSecond: PropTypes.bool,
    // onClear: PropTypes.func,
    use12Hours: PropTypes.bool.def(false),
    hourStep: PropTypes.number,
    minuteStep: PropTypes.number,
    secondStep: PropTypes.number,
    addon: PropTypes.func.def(noop),
    focusOnOpen: PropTypes.bool,
    // onKeydown: PropTypes.func,
    clearIcon: PropTypes.any,
  },
  data() {
    return {
      sValue: this.value,
      selectionRange: [],
      currentSelectPanel: '',
    };
  },
  watch: {
    value(val) {
      this.setState({
        sValue: val,
      });
    },
  },

  methods: {
    onChange(newValue) {
      this.setState({ sValue: newValue });
      this.__emit('change', newValue);
    },

    onAmPmChange(ampm) {
      this.__emit('amPmChange', ampm);
    },

    onCurrentSelectPanelChange(currentSelectPanel) {
      this.setState({ currentSelectPanel });
    },

    // https://github.com/ant-design/ant-design/issues/5829
    close() {
      this.__emit('esc');
    },
    onEsc(e) {
      this.__emit('esc', e);
    },
    disabledHours2() {
      const { use12Hours, disabledHours } = this;
      let disabledOptions = disabledHours();
      if (use12Hours && Array.isArray(disabledOptions)) {
        if (this.isAM()) {
          disabledOptions = disabledOptions.filter(h => h < 12).map(h => (h === 0 ? 12 : h));
        } else {
          disabledOptions = disabledOptions.map(h => (h === 12 ? 12 : h - 12));
        }
      }
      return disabledOptions;
    },

    isAM() {
      const value = this.sValue || this.defaultOpenValue;
      return value.hour() >= 0 && value.hour() < 12;
    },
  },

  render() {
    const {
      prefixCls,
      placeholder,
      disabledMinutes,
      addon,
      disabledSeconds,
      hideDisabledOptions,
      showHour,
      showMinute,
      showSecond,
      format,
      defaultOpenValue,
      clearText,
      use12Hours,
      focusOnOpen,
      hourStep,
      minuteStep,
      secondStep,
      inputReadOnly,
      sValue,
      currentSelectPanel,
    } = this;
    const { class: className, onEsc = noop, onKeydown = noop } = this.$attrs;
    const clearIcon = getComponent(this, 'clearIcon');

    const disabledHourOptions = this.disabledHours2();
    const disabledMinuteOptions = disabledMinutes(sValue ? sValue.hour() : null);
    const disabledSecondOptions = disabledSeconds(
      sValue ? sValue.hour() : null,
      sValue ? sValue.minute() : null,
    );
    const hourOptions = generateOptions(24, disabledHourOptions, hideDisabledOptions, hourStep);
    const minuteOptions = generateOptions(
      60,
      disabledMinuteOptions,
      hideDisabledOptions,
      minuteStep,
    );
    const secondOptions = generateOptions(
      60,
      disabledSecondOptions,
      hideDisabledOptions,
      secondStep,
    );
    const validDefaultOpenValue = toNearestValidTime(
      defaultOpenValue,
      hourOptions,
      minuteOptions,
      secondOptions,
    );
    return (
      <div className={classNames(className, `${prefixCls}-inner`)}>
        <Header
          clearText={clearText}
          prefixCls={prefixCls}
          defaultOpenValue={validDefaultOpenValue}
          value={sValue}
          currentSelectPanel={currentSelectPanel}
          onEsc={onEsc}
          format={format}
          placeholder={placeholder}
          hourOptions={hourOptions}
          minuteOptions={minuteOptions}
          secondOptions={secondOptions}
          disabledHours={this.disabledHours2}
          disabledMinutes={disabledMinutes}
          disabledSeconds={disabledSeconds}
          onChange={this.onChange}
          focusOnOpen={focusOnOpen}
          onKeydown={onKeydown}
          inputReadOnly={inputReadOnly}
          clearIcon={clearIcon}
        />
        <Combobox
          prefixCls={prefixCls}
          value={sValue}
          defaultOpenValue={validDefaultOpenValue}
          format={format}
          onChange={this.onChange}
          onAmPmChange={this.onAmPmChange}
          showHour={showHour}
          showMinute={showMinute}
          showSecond={showSecond}
          hourOptions={hourOptions}
          minuteOptions={minuteOptions}
          secondOptions={secondOptions}
          disabledHours={this.disabledHours2}
          disabledMinutes={disabledMinutes}
          disabledSeconds={disabledSeconds}
          onCurrentSelectPanelChange={this.onCurrentSelectPanelChange}
          use12Hours={use12Hours}
          onEsc={this.onEsc}
          isAM={this.isAM()}
        />
        {addon(this)}
      </div>
    );
  },
};

export default Panel;
