<template>
  <div class="el-year-month-spinner">
    <el-scrollbar
      @mouseenter.native="emitSelectRange('years')"
      @mousemove.native="adjustCurrentSpinner('years')"
      class="el-year-month-spinner__wrapper"
      wrap-style="max-height: inherit;"
      view-class="el-year-month-spinner__list"
      noresize
      tag="ul"
      ref="years">
      <li
        @click="handleClick('years', { value: item.value, disabled: item.disabled })"
        v-for="item in yearsList"
        class="el-year-month-spinner__item"
        :key="item.value"
        :class="{ 'active': item.value === years, 'disabled': item.disabled }">{{ item.value }}{{ item.value === years ? '年' : ''}}</li>
    </el-scrollbar>
    <el-scrollbar
      @mouseenter.native="emitSelectRange('months')"
      @mousemove.native="adjustCurrentSpinner('months')"
      class="el-year-month-spinner__wrapper"
      wrap-style="max-height: inherit;"
      view-class="el-year-month-spinner__list"
      noresize
      tag="ul"
      ref="months">
      <li
        @click="handleClick('months', { value: key, disabled: false })"
        v-for="(enabled, key) in monthsList"
        :key="key"
        class="el-year-month-spinner__item"
        :class="{ 'active': key === months, disabled: !enabled }">{{ ('0' + (key + 1)).slice(-2) }}{{key === months ? '月' : ''}}</li>
    </el-scrollbar>
  </div>
</template>

<script type="text/babel">
  import { getRangeYears, getRangeMonths, modifyYearMonthDate, dateWithinRange } from 'modesign-ui/src/utils/date-util';
  import ElScrollbar from 'modesign-ui/packages/scrollbar';
  import RepeatClick from 'modesign-ui/src/directives/repeat-click';

  export default {
    components: { ElScrollbar },

    directives: {
      repeatClick: RepeatClick
    },

    props: {
      date: {},
      defaultValue: {}, // reserved for future use
      disabledDate: {}
    },

    computed: {
      years() {
        return this.date.getFullYear();
      },
      months() {
        return this.date.getMonth();
      },
      yearsList() {
        return getRangeYears(this.selectableRange);
      },
      monthsList() {
        return getRangeMonths(this.selectableRange, this.years);
      }
    },

    data() {
      return {
        selectableRange: [],
        currentScrollbar: null
      };
    },

    mounted() {
      this.$nextTick(() => {
        this.bindScrollEvent();
        this.$emit('mounted');
      });
      this.initSpinnerHeight()
    },

    methods: {
      initSpinnerHeight() {
        const nowClient = document.getElementsByClassName('el-year-month-spinner__wrapper')[0]
        let style = document.createElement('style')
        document.head.appendChild(style)
        let sheet = style.sheet
        sheet.addRule('.el-year-month-spinner__list:after', `height: ${nowClient.clientHeight - 40}px;`);
        sheet.insertRule(`.el-year-month-spinner__list:after{height: ${nowClient.clientHeight - 40}px;}`);
      },
      isValidValue(date) {
        return dateWithinRange(date, this.selectableRange);
      },

      modifyDateField(type, value) {
        let date = null;
        if (type === 'years') {
          date = modifyYearMonthDate(this.date, value, this.months);
        } else {
          date = modifyYearMonthDate(this.date, this.years, value);
        }
        if (this.isValidValue(date)) {
          this.$emit('change', date);
        }
      },

      handleClick(type, {value, disabled}) {
        if (!disabled) {
          this.modifyDateField(type, value);
          this.emitSelectRange(type);
          this.adjustSpinner(type, value);
        }
      },

      emitSelectRange(type) {
        if (type === 'years') {
          this.$emit('select-range', 0, 2);
        } else if (type === 'months') {
          this.$emit('select-range', 3, 5);
        }
        this.currentScrollbar = type;
      },

      bindScrollEvent() {
        const bindFuntion = (type) => {
          this.$refs[type].wrap.onscroll = (e) => {
            // TODO: scroll is emitted when set scrollTop programatically
            // should find better solutions in the future!
            this.handleScroll(type, e);
          };
        };
        bindFuntion('years');
        bindFuntion('months');
      },

      handleScroll(type) {
        // 8 和 el-time-spinner__item的margin-top margin-bottom有关
        let value = Math.min(Math.round(this.$refs[type].wrap.scrollTop / (this.typeItemHeight(type) + 8)), (type === 'years' ? (this.yearsList.length - 1) : 12))
        if (type === 'years') {
          value = this.yearsList[value].value;
        }
        this.modifyDateField(type, value);
      },

      // NOTE: used by datetime / date-range panel
      //       renamed from adjustScrollTop
      //       should try to refactory it
      adjustSpinners() {
        this.adjustSpinner('years', this.years);
        this.adjustSpinner('months', this.months);
      },

      adjustCurrentSpinner(type) {
        this.adjustSpinner(type, this[type]);
      },

      adjustSpinner(type, value) {
        const el = this.$refs[type].wrap;
        if (el) {
          let i = value;
          if (type === 'years') {
            i = this.yearsList.findIndex(x => x.value === value)
          }
          // 8 和 el-time-spinner__item的margin-top margin-bottom有关
          el.scrollTop = Math.max(0, i * (this.typeItemHeight(type) + 8));
        }
      },

      scrollDown(step) {
        if (!this.currentScrollbar) {
          this.emitSelectRange('years');
        }

        const label = this.currentScrollbar;
        const yearsList = this.yearsList;
        let now = this[label];

        if (this.currentScrollbar === 'years') {
          let total = Math.abs(step);
          step = step > 0 ? 1 : -1;
          let length = yearsList.length;
          while (length-- && total) {
            now = (now + step + yearsList.length) % yearsList.length;
            if (yearsList[now]) {
              continue;
            }
            total--;
          }
          if (yearsList[now].disabled) return;
        } else {
          now = (now + step + 12) % 12;
        }
        this.modifyDateField(label, now);
        this.adjustSpinner(label, now);
        this.$nextTick(() => this.emitSelectRange(this.currentScrollbar));
      },
      typeItemHeight(type) {
        return this.$refs[type].$el.querySelector('li').offsetHeight;
      },
      scrollBarHeight(type) {
        return this.$refs[type].$el.offsetHeight;
      }
    }
  };
</script>
