<template>
    <div :class="[prefixCls + '-body-wrapper']" @mousedown.prevent>
        <div :class="[prefixCls + '-body']">
            <div :class="[timePrefixCls + '-header']" v-if="showDate">{{ visibleDate }}</div>
            <div :class="[prefixCls + '-content']">
                <time-spinner
                    ref="timeSpinner"
                    :show-seconds="showSeconds"
                    :steps="steps"
                    :hours="timeSlots[0]"
                    :minutes="timeSlots[1]"
                    :seconds="timeSlots[2]"
                    :disabled-hours="disabledHMS.disabledHours"
                    :disabled-minutes="disabledHMS.disabledMinutes"
                    :disabled-seconds="disabledHMS.disabledSeconds"
                    :hide-disabled-options="hideDisabledOptions"
                    @on-change="handleChange"
                    @on-pick-click="handlePickClick"></time-spinner>
            </div>
            <Confirm
                v-if="confirm"
                @on-pick-clear="handlePickClear"
                @on-pick-success="handlePickSuccess"></Confirm>
        </div>
    </div>
</template>
<script>
    import TimeSpinner from '../../base/time-spinner.vue';
    import Confirm from '../../base/confirm.vue';
    import Options from '../../time-mixins';


    import Mixin from '../panel-mixin';
    import Locale from '../../../../mixins/locale';

    import { initTimeDate } from '../../util';

    const prefixCls = 'ivu-picker-panel';
    const timePrefixCls = 'ivu-time-picker';

    const capitalize = (str) => str[0].toUpperCase() + str.slice(1);
    const mergeDateHMS = (date, hours, minutes, seconds) => {
        const newDate = new Date(date.getTime());
        newDate.setHours(hours);
        newDate.setMinutes(minutes);
        newDate.setSeconds(seconds);
        return newDate;
    };
    const unique = (el, i, arr) => arr.indexOf(el) === i;
    const returnFalse = () => false;

    export default {
        name: 'TimePickerPanel',
        mixins: [ Mixin, Locale, Options ],
        components: { TimeSpinner, Confirm },
        emits: ['on-pick'],
        props: {
            disabledDate: {
                type: Function,
                default: returnFalse
            },
            steps: {
                type: Array,
                default: () => []
            },
            format: {
                type: String,
                default: 'HH:mm:ss'
            },
            modelValue: {
                type: Array,
                required: true
            },
        },
        data () {
            return {
                prefixCls: prefixCls,
                timePrefixCls: timePrefixCls,
                date: this.modelValue[0] || initTimeDate(),
                showDate: false
            };
        },
        computed: {
            showSeconds () {
                //fix Hour & Minute Picker bug,show seconds when has "ss"
                return !!(this.format || '').match(/ss/);
            },
            visibleDate () { // TODO
                const date = this.date;
                const month = date.getMonth() + 1;
                const tYear = this.t('i.datepicker.year');
                const tMonth = this.t(`i.datepicker.month${month}`);
                return `${date.getFullYear()}${tYear} ${tMonth}`;
            },
            timeSlots(){
                if (!this.modelValue[0]) return [];
                return ['getHours', 'getMinutes', 'getSeconds'].map(slot => this.date[slot]());
            },
            disabledHMS(){
                const disabledTypes = ['disabledHours', 'disabledMinutes', 'disabledSeconds'];
                if (this.disabledDate === returnFalse || !this.modelValue[0]) {
                    const disabled = disabledTypes.reduce(
                        (obj, type) => (obj[type] = this[type], obj), {}
                    );
                    return disabled;
                } else {
                    const slots = [24, 60, 60];
                    const disabled = ['Hours', 'Minutes', 'Seconds'].map(type => this[`disabled${type}`]);
                    const disabledHMS = disabled.map((preDisabled, j) => {
                        const slot = slots[j];
                        const toDisable = preDisabled;
                        for (let i = 0; i < slot; i+= (this.steps[j] || 1)){
                            const hms = this.timeSlots.map((slot, x) => x === j ? i : slot);
                            const testDateTime = mergeDateHMS(this.date, ...hms);
                            if (this.disabledDate(testDateTime, true)) toDisable.push(i);
                        }
                        return toDisable.filter(unique);
                    });
                    return disabledTypes.reduce(
                        (obj, type, i) => (obj[type] = disabledHMS[i], obj), {}
                    );
                }
            }
        },
        watch: {
            modelValue (dates) {
                let newVal = dates[0] || initTimeDate();
                newVal = new Date(newVal);
                this.date = newVal;
            }
        },
        methods: {
            handleChange (date, emit = true) {

                const newDate = new Date(this.date);
                Object.keys(date).forEach(
                    type => newDate[`set${capitalize(type)}`](date[type])
                );

                if (emit) this.$emit('on-pick', newDate, 'time');
            },
        },
        mounted () {
            if (this.$parent && this.$parent.$options.name === 'DatePicker') this.showDate = true;
        }
    };
</script>
