<template>
    <div :class="classes">
        <div :class="[prefixCls + '-list']" ref="hours">
            <vue-scroll :ops="vueScrollConfig">
                <ul :class="[prefixCls + '-ul']">
                    <li
                        :class="getCellCls(item)"
                        v-for="item in hoursList"
                        v-show="!item.hide"
                        @click="handleClick('hours', item)"
                    >
                        {{ formatTime(item.text) }}
                    </li>
                </ul>
            </vue-scroll>
        </div>
        <div :class="[prefixCls + '-list']" ref="minutes">
            <vue-scroll :ops="vueScrollConfig">
                <ul :class="[prefixCls + '-ul']">
                    <li
                        :class="getCellCls(item)"
                        v-for="item in minutesList"
                        v-show="!item.hide"
                        @click="handleClick('minutes', item)"
                    >
                        {{ formatTime(item.text) }}
                    </li>
                </ul>
            </vue-scroll>
        </div>
        <div
            :class="[prefixCls + '-list']"
            v-show="showSeconds"
            ref="seconds"
        >
            <vue-scroll :ops="vueScrollConfig">
                <ul :class="[prefixCls + '-ul']">
                    <li
                        :class="getCellCls(item)"
                        v-for="item in secondsList"
                        v-show="!item.hide"
                        @click="handleClick('seconds', item)"
                    >
                        {{ formatTime(item.text) }}
                    </li>
                </ul>
            </vue-scroll>
        </div>
    </div>
</template>
<script>
import Options from '../time-mixins';
import {
    deepCopy,
    scrollTop,
    firstUpperCase
} from '../../../utils/assist';
import vueScroll from 'vuescroll/dist/vuescroll-native';
import vueScrollConfig from '../../../mixins/vueScrollConfig';
const prefixCls = 'ivu-time-picker-cells';
const timeParts = ['hours', 'minutes', 'seconds'];

export default {
    components: { vueScroll },
    name: 'TimeSpinner',
    mixins: [Options],
    props: {
        hours: {
            type: [Number, String],
            default: NaN
        },
        minutes: {
            type: [Number, String],
            default: NaN
        },
        seconds: {
            type: [Number, String],
            default: NaN
        },
        showSeconds: {
            type: Boolean,
            default: true
        },
        steps: {
            type: Array,
            default: () => []
        }
    },
    data() {
        return {
            vueScrollConfig,
            spinerSteps: [1, 1, 1].map(
                (one, i) => Math.abs(this.steps[i]) || one
            ),
            prefixCls: prefixCls,
            compiled: false,
            focusedColumn: -1, // which column inside the picker
            focusedTime: [0, 0, 0] // the values array into [hh, mm, ss]
        };
    },
    computed: {
        classes() {
            return [
                `${prefixCls}`,
                {
                    [`${prefixCls}-with-seconds`]:
                        this.showSeconds
                }
            ];
        },
        hoursList() {
            let hours = [];
            const step = this.spinerSteps[0];
            const focusedHour =
                this.focusedColumn === 0 && this.focusedTime[0];
            const hour_tmpl = {
                text: 0,
                selected: false,
                disabled: false,
                hide: false
            };

            for (let i = 0; i < 24; i += step) {
                const hour = deepCopy(hour_tmpl);
                hour.text = i;
                hour.focused = i === focusedHour;

                if (
                    this.disabledHours.length &&
                    this.disabledHours.indexOf(i) > -1
                ) {
                    hour.disabled = true;
                    if (this.hideDisabledOptions)
                        hour.hide = true;
                }
                if (this.hours === i) hour.selected = true;
                hours.push(hour);
            }

            return hours;
        },
        minutesList() {
            let minutes = [];
            const step = this.spinerSteps[1];
            const focusedMinute =
                this.focusedColumn === 1 && this.focusedTime[1];
            const minute_tmpl = {
                text: 0,
                selected: false,
                disabled: false,
                hide: false
            };

            for (let i = 0; i < 60; i += step) {
                const minute = deepCopy(minute_tmpl);
                minute.text = i;
                minute.focused = i === focusedMinute;

                if (
                    this.disabledMinutes.length &&
                    this.disabledMinutes.indexOf(i) > -1
                ) {
                    minute.disabled = true;
                    if (this.hideDisabledOptions)
                        minute.hide = true;
                }
                if (this.minutes === i) minute.selected = true;
                minutes.push(minute);
            }
            return minutes;
        },
        secondsList() {
            let seconds = [];
            const step = this.spinerSteps[2];
            const focusedMinute =
                this.focusedColumn === 2 && this.focusedTime[2];
            const second_tmpl = {
                text: 0,
                selected: false,
                disabled: false,
                hide: false
            };

            for (let i = 0; i < 60; i += step) {
                const second = deepCopy(second_tmpl);
                second.text = i;
                second.focused = i === focusedMinute;

                if (
                    this.disabledSeconds.length &&
                    this.disabledSeconds.indexOf(i) > -1
                ) {
                    second.disabled = true;
                    if (this.hideDisabledOptions)
                        second.hide = true;
                }
                if (this.seconds === i) second.selected = true;
                seconds.push(second);
            }

            return seconds;
        }
    },
    methods: {
        getCellCls(cell) {
            return [
                `${prefixCls}-cell`,
                {
                    [`${prefixCls}-cell-selected`]:
                        cell.selected,
                    [`${prefixCls}-cell-focused`]: cell.focused,
                    [`${prefixCls}-cell-disabled`]: cell.disabled
                }
            ];
        },
        chooseValue(values) {
            const changes = timeParts.reduce((obj, part, i) => {
                const value = values[i];
                if (this[part] === value) return obj;
                return {
                    ...obj,
                    [part]: value
                };
            }, {});
            if (Object.keys(changes).length > 0) {
                this.emitChange(changes);
            }
        },
        handleClick(type, cell) {
            if (cell.disabled) return;
            const data = { [type]: cell.text };
            this.emitChange(data);
        },
        emitChange(changes) {
            this.$emit('on-change', changes);
            this.$emit('on-pick-click');
        },
        scroll(type, index) {
            const from = this.$refs[type].scrollTop;
            const to = 24 * this.getScrollIndex(type, index);
            scrollTop(this.$refs[type], from, to, 500);
        },
        getScrollIndex(type, index) {
            const Type = firstUpperCase(type);
            const disabled = this[`disabled${Type}`];
            if (disabled.length && this.hideDisabledOptions) {
                let _count = 0;
                disabled.forEach(item =>
                    item <= index ? _count++ : ''
                );
                index -= _count;
            }
            return index;
        },
        updateScroll() {
            this.$nextTick(() => {
                timeParts.forEach(type => {
                    this.$refs[type].scrollTop =
                        24 *
                        this[`${type}List`].findIndex(
                            obj => obj.text == this[type]
                        );
                });
            });
        },
        formatTime(text) {
            return text < 10 ? '0' + text : text;
        },
        updateFocusedTime(col, time) {
            this.focusedColumn = col;
            this.focusedTime = time.slice();
        }
    },
    watch: {
        hours(val) {
            if (!this.compiled) return;
            this.scroll(
                'hours',
                this.hoursList.findIndex(obj => obj.text == val)
            );
        },
        minutes(val) {
            if (!this.compiled) return;
            this.scroll(
                'minutes',
                this.minutesList.findIndex(
                    obj => obj.text == val
                )
            );
        },
        seconds(val) {
            if (!this.compiled) return;
            this.scroll(
                'seconds',
                this.secondsList.findIndex(
                    obj => obj.text == val
                )
            );
        },
        focusedTime(updated, old) {
            timeParts.forEach((part, i) => {
                if (
                    updated[i] === old[i] ||
                    typeof updated[i] === 'undefined'
                )
                    return;
                const valueIndex = this[`${part}List`].findIndex(
                    obj => obj.text === updated[i]
                );
                this.scroll(part, valueIndex);
            });
        }
    },
    mounted() {
        this.$nextTick(() => (this.compiled = true));
    }
};
</script>
