/// <reference path="./definition.d.ts" />

import * as React from 'react';
import view from '../picker/view';
import {
  createYearArray,
  createMinutesAndSecondsArray,
  createHoursArray,
  createMonthArray,
  getDaysInMonth,
  getDefaultValue,
  valueFormat,
  getTodayDate
} from '../util/date';
// import { setTranslate } from '../util/transform';
import PickerCore from '../picker/core';

const prefix = 'tsp-component-Picker';
function formatLabel(selected: TspComponentPickerValues[]): string {
  let label = '';
  for (let i = 0; i < selected.length; i++) {
    const value = selected[i].value;
    if (i < 2) {
      label += value + '-';
    } else if (i === 3) {
      label +=  ' ' + value;
    } else if (i === 4) {
      label += ':' + value;
    } else {
      label += value;
    }
  }
  return label;
}
class DatePicker extends React.Component<TspComponentDatePickerProps, any> {
  constructor(props: TspComponentDatePickerProps, state: any) {
    super(props, state);
    this.onPanStart = this.onPanStart.bind(this);
    this.onPan = this.onPan.bind(this);
    this.onPanEnd = this.onPanEnd.bind(this);
    this.onOk = this.onOk.bind(this);
    this.onCancel = this.onCancel.bind(this);
    this.onOpen = this.onOpen.bind(this);
    this.onTransitionEnd = this.onTransitionEnd.bind(this);
  }

  public static defaultProps: TspComponentDatePickerProps = {
    id: '',
    cascade: false,
    defaultValue: getDefaultValue(),
    startDate: getTodayDate(),
    endDate: getTodayDate(),
    enableStartDate: false,
    enableEndDate: false,
    mode: 'yyMMddHHmm',
    //defaultLabel: formatLabel(getDefaultValue()),
    formatLabel
  };

  /**
   * PickerCore实例
   */
  private core: PickerCore;
  /**
   * 触发transitionEnd的timeout返回对象
   */
  private transitionEndTimeout: number;

  public shouldComponentUpdate(nextProps: TspComponentDatePickerProps): boolean {
    return this.props.updateId !== nextProps.updateId;
  }

  public componentDidMount(): void {
    const value = this.props.defaultValue.slice(0, 5).map((item) => item.value).join('');
    const startDate = this.props.startDate.join('');
    const endDate = this.props.endDate.join('');

    if (value < startDate && this.props.enableStartDate) {
      console.error('value设定值不能小于startDate的设定值');
      return;
    }
    if (value > endDate && this.props.enableEndDate) {
      console.error('value设定值不能超过endDate的设定值');
      return;
    }

    this.core = new PickerCore({
      id: this.props.id,
      cascade: false,
      defaultValue: this.props.defaultValue,
      onOk: this.props.onOk,
      defaultLabel: this.props.defaultLabel,
      data: [],
      sliderElem: this.refs.slider as HTMLElement,
      containerElem: this.refs.container['elem'] as HTMLElement,
      labelElem: this.refs.label as HTMLElement,
      formatLabel: this.props.formatLabel
    });

    this.core.data = this.setMode();
    this.core.init();
    // this.onTransitionEnd();
    this.core.sliderElem.addEventListener('webkitTransitionEnd', this.onTransitionEnd);
  }

  public componentWillReceiveProps(nextProps: TspComponentDatePickerProps): void {
    // this.core.componentWillReceiveProps(this.props, nextProps);
  }

  public componentDidUpdate(prevProps: TspComponentDatePickerProps): void {
    this.core.data = this.setMode();
    this.core.componentWillReceiveProps(prevProps, this.props);
  }

  /**
   * 开始拖动
   */
  public onPanStart(evt: TspComponentSliderEvt): void {
    evt.preventDefault();
    this.core.panStart(evt);
  }

  /**
   * 拖动中
   */
  public onPan(evt: TspComponentSliderEvt): void {
    evt.preventDefault();
    this.core.pan(evt);
  }

  /**
   * 拖动结束后
   */
  public onPanEnd(evt: TspComponentSliderEvt): void {
    evt.preventDefault();
    this.core.panEnd(evt);
    if (this.core.isPanEnd && this.core.touchElementCol !== undefined) {
      this.transitionEndTimeout = setTimeout(() => {
        if (!this.core.isTransitionEnd) {
          this.onTransitionEnd();
        }
      }, 300);
    }
  }

  /**
   * 监听translate完成事件
   */
  public onTransitionEnd(): void {
    this.core.transitionEnd(this.transitionEndTimeout);
    this.reset();
  }

  /**
   * 重置
   */
  public reset(): void {
    switch (this.props.mode) {
      case 'yyMMdd':
      case 'yyMMddHH':
      case 'yyMMddHHmm':
        if (this.props.enableStartDate || this.props.enableEndDate) {
          if (this.core.touchElementCol === 0 || this.core.touchElementCol === 1) {
            const year = parseInt(this.core.data[0][this.core.getValueIndex(0, this.core.selected)].value.toString());
            const month = parseInt(this.core.data[1][this.core.getValueIndex(1, this.core.selected)].value.toString()) - 1;
            const day = parseInt(this.core.data[2][this.core.getValueIndex(2, this.core.selected)].value.toString());

            if (this.core.touchElementCol === 0) {
              this.replaceMonth(year);
            } else if (this.core.touchElementCol === 1) {
              this.replaceDays(year, month, day);
            }
          }
        } else {
          this.renderDays();
        }
        break;
      default: break;
    }
  }

  /**
   * 确定
   */
  public onOk(): void {
    this.core.ok();
  }
  /**
   * 取消
   */
  public onCancel(): void {
    this.core.cancel();
  }

  /**
   * 打开
   */
  public onOpen(): void {
    if (!this.props.disabled) {
      this.reset();
      this.core['value'] = this.core.selected;
      this.core.open();
    }
  }

  /** 设置日期模式 */
  // tslint:disable-next-line:max-line-length
  // tslint:disable-next-line:array-type
  public setMode(yearIndex: number = this.props.defaultValue[0].index, monthIndex: number = this.props.defaultValue[1].index): { value: string | number, label: number | string }[][] {
    const mode = this.props.mode;
    const startYear = parseInt(this.props.startDate[0].toString());
    const endYear = parseInt(this.props.endDate[0].toString());
    const startMonth = parseInt(this.props.startDate[1].toString());
    const endMonth = parseInt(this.props.endDate[1].toString());
    const startDay = parseInt(this.props.startDate[2].toString());
    const endDay = parseInt(this.props.endDate[2].toString());
    let year = yearIndex !== undefined ? startYear + yearIndex : this.props.defaultValue[0].value;
    let month =  monthIndex !== undefined ? monthIndex : parseInt(this.props.defaultValue[1].value.toString()) - 1;
    let [yy, MM, dd, HH, mm] = [undefined, undefined, undefined, undefined, undefined];

    if (mode.indexOf('yy') >= 0) {
      const startDate = parseInt(this.props.startDate[0]);
      const endDate = parseInt(this.props.endDate[0]);
      yy = createYearArray(startDate, endDate, 'array').map((value) => valueFormat(value, 'object', '年'));
    }

    year = parseInt(year.toString());
    month = parseInt(month.toString());

    if (mode.indexOf('MM') >= 0) {
      MM = createMonthArray('array').map((value) => valueFormat(value + 1, 'object', '月'));
      if (this.props.enableStartDate && year === startYear) {
        if (this.props.startDate.length >= 2) {
          MM = MM.slice(startMonth - 1);
        } else {
          console.error('startDate设置错误，startDate数组长度不足2维');
        }
      }
      if (this.props.enableEndDate && year === endYear) {
        if (this.props.endDate.length >= 2) {
          MM = MM.slice(0, endMonth - startMonth + 1);
        } else {
          console.error('endDate设置错误，endDate数组长度不足2维');
        }
      }
    }

    if (mode.indexOf('dd') >= 0) {
      dd = getDaysInMonth(year, month, 'array').map((value) => valueFormat(value, 'object', '日'));
      if (this.props.enableStartDate && year === startYear && month === startMonth - 1) {
        if (this.props.startDate.length >= 3) {
          dd = dd.slice(startDay - 1);
        } else {
          console.error('startDate设置错误，startDate数组长度不等于3维');
        }
      }

      if (this.props.enableEndDate && year === endYear && month === endMonth - 1) {
        if (this.props.endDate.length >= 3) {
          dd = dd.slice(0, endDay);
        } else {
          console.error('endDate设置错误，endDate数组长度不足3维');
        }
      }
    }

    if (mode.indexOf('HH') >= 0) {
      HH = createHoursArray('array').map((value) => valueFormat(value, 'object', '时'));
    }

    if (mode.indexOf('mm') >= 0) {
      mm = createMinutesAndSecondsArray('array').map((value) => valueFormat(value, 'object', '分'));
    }

    switch (mode) {
      case 'yy': return [yy];
      case 'yyMM': return [yy, MM];
      case 'yyMMdd': return [yy, MM, dd];
      case 'yyMMddHH': return [yy, MM, dd, HH];
      case 'yyMMddHHmm': return [yy, MM, dd, HH, mm];
      case 'HHmm': return  [HH, mm];
      default: break;
    }
  }

  /**
   * 渲染天数
   */
  public renderDays(): void {
    const data = this.core.data;
    const year = parseInt(data[0][this.core.getValueIndex(0, this.core.selected)].value.toString());
    const month = parseInt(data[1][this.core.getValueIndex(1, this.core.selected)].value.toString()) - 1;
    const days = getDaysInMonth(year, month, 'array').map((value) => valueFormat(value, 'object', '日'));
    const oldLength = data[2].length;
    const newLength = days.length;
    const parent = this.core.sliderElem.children[2];
    const fragment = document.createDocumentFragment();
    const length = oldLength > newLength ? oldLength : newLength;
    const flag = oldLength > newLength ? 1 : 2;

    if (oldLength === newLength) {
      return;
    }

    parent.innerHTML = null;

    for (let i = 0; i < length; i++) {
      const tempElem = document.createElement('div');
      tempElem.classList.add(`${prefix}-body-col-item`);
      tempElem.innerText = valueFormat(i + 1, 'string', '日');
      fragment.appendChild(tempElem);
    }

    parent.appendChild(fragment);
    this.core.data[2] = days;
    const selected = this.core.getValueIndex(2, this.core.selected);
    this.core.pickerTranslateInitial(2, this.core.data[2][selected] ? selected : 0);
  }

  public replaceMonth(year: number): void {
    const { startDate, endDate, enableStartDate, enableEndDate } = this.props;
    const startYear = parseInt(startDate[0].toString());
    const endYear = parseInt(endDate[0].toString());
    const enableStartYear = year === startYear && enableStartDate;
    const enableEndYear = year === endYear && enableEndDate;
    const startMonth = parseInt(startDate[1].toString());
    const endMonth = parseInt(endDate[1].toString());
    const selectedMonth = parseInt(this.core.selected[1].value.toString());
    let [month, day] = [undefined, undefined];

    if (enableStartYear || enableEndYear) {
      if (enableStartYear) {
          month = selectedMonth < startMonth ? startMonth : selectedMonth;
      } else {
          month = selectedMonth > endMonth ? endMonth : selectedMonth;
      }

      this.core.data = this.setMode(this.core.selected[0].index, month - 1);
      this.core.renderCol(this.core.data[1], 1, 'replace');
      if (!enableStartYear) {
        this.core.selected[1].index = undefined;
        this.core.selected[1].value = valueFormat(month, 'string', '月');
      }

      this.core.pickerTranslateInitial(1, this.core.getValueIndex(1, this.core.selected));
      const dayValueIndex = this.core.getValueIndex(2, this.core.selected);
      const dayIndex = this.core.data[2].length > dayValueIndex ? dayValueIndex : 0;
      day = parseInt(this.core.data[2][dayIndex].value.toString());
      this.replaceDays(year, month - 1, day);
    } else {
        this.renderDays();
        this.core.data = this.setMode(this.core.selected[0].index, selectedMonth - 1);
        this.core.renderCol(this.core.data[1], 1, 'replace');
        this.core.pickerTranslateInitial(1, this.core.getValueIndex(1, this.core.selected));
    }
  }

  public replaceDays(year: number, month: number, day: number): void {
    const { startDate, endDate, enableStartDate, enableEndDate } = this.props;
    const startYear = parseInt(startDate[0].toString());
    const endYear = parseInt(endDate[0].toString());
    const startMonth = parseInt(startDate[1].toString()) - 1;
    const endMonth = parseInt(endDate[1].toString()) - 1;
    const startMatch = year === startYear && month === startMonth && enableStartDate;
    const endMatch = year === endYear && month === endMonth && enableEndDate;

    if (startMatch || endMatch) {
      this.core.data = this.setMode(this.core.selected[0].index, month);
      this.core.renderCol(this.core.data[2], 2, 'replace');
      this.core.selected[2].index = undefined;
      this.core.selected[2].value = valueFormat(day, 'string', '月');
      this.core.pickerTranslateInitial(2, this.core.getValueIndex(2, this.core.selected));
    } else {
      this.renderDays();
    }
  }

  public render(): JSX.Element {
    return view(this);
  }
}

export default DatePicker;