import { createNamespace } from '../utils';
import { isDate } from '../utils/validate/date';
import { padZero } from '../utils/format/string';
import { getTrueValue, getMonthEndDay } from './utils';
import { sharedProps, TimePickerMixin } from './shared';

const currentYear = new Date().getFullYear();
const [createComponent] = createNamespace('date-picker');

export default createComponent({
  mixins: [TimePickerMixin],

  props: {
    ...sharedProps,
    type: {
      type: String,
      default: 'datetime'
    },
    minDate: {
      type: Date,
      default: () => new Date(currentYear - 10, 0, 1),
      validator: isDate
    },
    maxDate: {
      type: Date,
      default: () => new Date(currentYear + 10, 11, 31),
      validator: isDate
    }
  },

  watch: {
    value(val) {
      val = this.formatValue(val);

      if (val.valueOf() !== this.innerValue.valueOf()) {
        this.innerValue = val;
      }
    }
  },

  computed: {
    ranges() {
      const { maxYear, maxDate, maxMonth, maxHour, maxMinute } = this.getBoundary(
        'max',
        this.innerValue
      );

      const { minYear, minDate, minMonth, minHour, minMinute } = this.getBoundary(
        'min',
        this.innerValue
      );

      const result = [
        {
          type: 'year',
          range: [minYear, maxYear]
        },
        {
          type: 'month',
          range: [minMonth, maxMonth]
        },
        {
          type: 'day',
          range: [minDate, maxDate]
        },
        {
          type: 'hour',
          range: [minHour, maxHour]
        },
        {
          type: 'minute',
          range: [minMinute, maxMinute]
        }
      ];

      if (this.type === 'date') result.splice(3, 2);
      if (this.type === 'year-month') result.splice(2, 3);
      return result;
    }
  },

  methods: {
    formatValue(value) {
      if (!isDate(value)) {
        value = this.minDate;
      }

      value = Math.max(value, this.minDate.getTime());
      value = Math.min(value, this.maxDate.getTime());

      return new Date(value);
    },

    getBoundary(type, value) {
      const boundary = this[`${type}Date`];
      const year = boundary.getFullYear();
      let month = 1;
      let date = 1;
      let hour = 0;
      let minute = 0;

      if (type === 'max') {
        month = 12;
        date = getMonthEndDay(value.getFullYear(), value.getMonth() + 1);
        hour = 23;
        minute = 59;
      }

      if (value.getFullYear() === year) {
        month = boundary.getMonth() + 1;
        if (value.getMonth() + 1 === month) {
          date = boundary.getDate();
          if (value.getDate() === date) {
            hour = boundary.getHours();
            if (value.getHours() === hour) {
              minute = boundary.getMinutes();
            }
          }
        }
      }

      return {
        [`${type}Year`]: year,
        [`${type}Month`]: month,
        [`${type}Date`]: date,
        [`${type}Hour`]: hour,
        [`${type}Minute`]: minute
      };
    },

    onChange(picker) {
      const values = picker.getValues();
      const year = getTrueValue(values[0]);
      const month = getTrueValue(values[1]);
      const maxDate = getMonthEndDay(year, month);

      let date = getTrueValue(values[2]);
      if (this.type === 'year-month') {
        date = 1;
      }

      date = date > maxDate ? maxDate : date;

      let hour = 0;
      let minute = 0;

      if (this.type === 'datetime') {
        hour = getTrueValue(values[3]);
        minute = getTrueValue(values[4]);
      }

      const value = new Date(year, month - 1, date, hour, minute);

      this.innerValue = this.formatValue(value);

      this.$nextTick(() => {
        this.$nextTick(() => {
          this.$emit('change', picker);
        });
      });
    },

    updateColumnValue(value) {
      const { formatter } = this;
      let values = [
        formatter('year', `${value.getFullYear()}`),
        formatter('month', padZero(value.getMonth() + 1)),
        formatter('day', padZero(value.getDate()))
      ];

      if (this.type === 'datetime') {
        values.push(
          formatter('hour', padZero(value.getHours())),
          formatter('minute', padZero(value.getMinutes()))
        );
      }

      if (this.type === 'year-month') {
        values = values.slice(0, 2);
      }

      this.$nextTick(() => {
        this.$refs.picker.setValues(values);
      });
    }
  }
});
