<template>
    <div v-clickoutside="close"
         :class="`${prefix}-date-picker`">
        <jdd-input ref="ipt"
                   v-model="displayValue"
                   :iconSuffix="`${prefix}-icon-calendar`"
                   :placeholders="placeholders"
                   clearable
                   readonly
                   mode="range"
                   :size="realSize"
                   :disabled="pickerDisabled"
                   @click="handleInputClick">
            <span slot="rangeSeperator">至</span>
        </jdd-input>

        <transition name="ani-slide"
                    @after-leave="doDestroy">
            <div v-if="visible"
                 ref="popper"
                 :style="datePickerStyle"
                 :class="`${prefix}-date-picker__panel`"
                 @click.stop>
                <quick-bar v-if="quickVisible"
                           :quickOptions="quickOptions"
                           @quick="handleQuick"></quick-bar>
                <picker v-model="viewDate">
                    <p v-for="item in title"
                       :key="item"
                       slot="title"
                       class="cont">{{item}}</p>
                    <date-table :start="hoverRange[0]"
                                :end="hoverRange[1]"
                                :date="viewDate"
                                :range="range"
                                @select="handleSelect"
                                @hover="handleHover"></date-table>
                    <date-table :start="hoverRange[0]"
                                :end="hoverRange[1]"
                                :date="nextViewDate"
                                :range="range"
                                @hover="handleHover"
                                @select="handleSelect"></date-table>
                </picker>
            </div>
        </transition>
    </div>
</template>

<script>
import Input from 'jdd-design/components/input';
import dayjs from 'dayjs';
import Picker from './picker';
import QuickBar from './quick-bar';
import DateTable from './date-table';
import pickerMixins from './mixins';
import { prefix, prefixMixins, on, off } from 'jdd-design/utils';
import clickoutside from 'jdd-design/utils/directives/clickoutside';
import transfer from 'jdd-design/utils/directives/transfer-dom';
import poperMixins from 'jdd-design/utils/mixins/popper';
export default {
    name: 'range-picker',
    mixins: [prefixMixins, pickerMixins, poperMixins],
    directives: { clickoutside, transfer },
    components: {
        DateTable,
        jddInput: Input,
        Picker,
        QuickBar
    },
    data() {
        return {
            hoverRange: [],
            selectedRange: [],
            quickOptions: [
                {
                    title: '最近一周',
                    getter: function() {
                        return [dayjs().add(-7, 'days'), dayjs()];
                    }
                },
                {
                    title: '最近一月',
                    getter: function() {
                        return [dayjs().add(-1, 'months'), dayjs()];
                    }
                }
            ]
        };
    },
    inject: {
        jddForm: {
            default: null
        },
        jddFormItem: {
            default: null
        }
    },
    provide() {
        return {
            jddDatePanel: this
        };
    },
    props: {
        value: Array,
        size: {
            type: String,
            default: 'medium'
        },
        placeholders: {
            type: Array,
            default: () => ['开始日期', '结束日期']
        },
        range: [Array, Function]
    },
    watch: {
        viewDate: function(val) {
            this.nextViewDate = this.fixTime(dayjs(val).add(1, 'month'));
        },
        visible: function(val) {
            this.$nextTick(() => {
                if (val) {
                    this.initPopper();
                    this.updatePopper();
                }
            });
        },
        value: function(val) {
            this.selectedRange = [...val.map(m => m && this.fixTime(m))];
            this.hoverRange = [...this.selectedRange];
            this.viewDate = this.fixTime(this.selectedRange[0]);
        }
    },
    computed: {
        title() {
            return [this.viewDate, this.nextViewDate].map(m =>
                dayjs(m).format('YYYY年MM月')
            );
        },
        displayValue: {
            get: function() {
                if (this.selectedRange.length === 2) {
                    return this.selectedRange.map(m =>
                        dayjs(m).format(this.formatter)
                    );
                }
                return ['', ''];
            },
            set: function(val) {
                this.selectedRange = [];
                this.hoverRange = [];
                this.viewDate = this.fixTime();
                this.$emit('input', this.selectedRange);
            }
        },
        realSize() {
            return this.size || (this.jddForm && this.jddForm.size) || 'medium';
        },
        quickVisible() {
            return (
                this.quickBar &&
                Object.prototype.toString.apply(this.range).toLowerCase() !==
                    '[object function]'
            );
        }
    },
    methods: {
        handleQuick(obj) {
            let quickDateStart = obj[0];
            let quickDateEnd = obj[1];
            let rangeType = Object.prototype.toString
                .apply(this.range)
                .toLowerCase();
            if (rangeType === '[object array]') {
                let disabledStart = this.fixTime(this.range[0]);
                let disabledEnd = this.fixTime(this.range[1]);
                obj = [
                    Math.max(quickDateStart, disabledStart),
                    Math.min(quickDateEnd, disabledEnd)
                ];
            } else if (rangeType === '[object function]') {
                throw new Error('can not user quickBar when range is function');
            }

            this.selectedRange = [...obj];
            this.hoverRange = [...obj];
            this.$emit('input', this.selectedRange);
            this.change();
            this.close();
        },
        handleInputClick() {
            if (this.pickerDisabled) return;
            this.viewDate = this.fixTime(this.selectedRange[0]);
            this.visible = true;
        },
        handleHover(date) {
            if (this.selectedRange.length === 1) {
                let sel = this.selectedRange[0];
                if (date > sel) {
                    this.hoverRange = [sel, date];
                } else {
                    this.hoverRange = [date, sel];
                }
            }
        },
        handleSelect(date, state) {
            if (this.selectedRange.length === 1) {
                let tmpDate = this.selectedRange[0];
                if (tmpDate < date) {
                    this.selectedRange = [tmpDate, date];
                } else {
                    this.selectedRange = [date, tmpDate];
                }
                this.hoverRange = [...this.selectedRange];
                this.$emit('input', this.selectedRange);
                this.change();
                this.close();
            } else {
                this.selectedRange = [date];
                this.hoverRange = [date, date];
            }
            if (state == 'prev') {
                this.viewDate = this.fixTime(
                    dayjs(this.viewDate).add(-1, 'months')
                );
            } else if (state == 'next') {
                this.viewDate = this.fixTime(
                    dayjs(this.viewDate).add(1, 'months')
                );
            }
        },
        close() {
            this.visible = false;
        },
        initPopper() {
            this.referenceElm = this.$refs.ipt.$el;
            this.popperElm = this.$refs.popper;
            this.currentPlacement = 'bottom-start';
        }
    },
    mounted() {
        this.selectedRange = [...this.value.map(m => m && this.fixTime(m))];
        this.hoverRange = [...this.selectedRange];
        this.viewDate = this.fixTime(this.selectedRange[0]);
        let width = 544;
        !this.quickVisible && (width -= 100);
        if (
            this.quickVisible &&
            Object.prototype.toString.apply(this.quickBar) == '[object Array]'
        ) {
            this.quickOptions = [...this.quickBar];
        }
        this.datePickerStyle.width = `${width}px`;
        this.initPopper();
        on(window, 'wheel', this.mouseWheel);
    },
    beforeDestory() {
        off(window, 'wheel', this.mouseWheel);
    }
};
</script>
