<template>
    <nu-picker
        v-bind="$props"
        :lists="myLists"
        :filterLinkage="_filterLinkage"
        :initMap="myInitMap"
        :selectList.sync="mySelectList"
        :selectChange="_selectChange"
        @confirmChange="_onConfirm"
        @cancelChange="_cancel">
    </nu-picker>
</template>
<script>
/* eslint-disable max-lines */
import { extend, formatDate, DateTime, toDate, callFn } from 'nimble-lib';
import PickerTmp from '../../base/picker/_comm/PickerTmp';
import NuPicker from '../../base/picker';
import confirm from '../../../Mixins/confirm';

export default {
    name: 'NuDatepicker',
    extends: PickerTmp,
    components: {
        NuPicker
    },
    props: {
        /**
         * DateTime的默认参数
         */
        options: {},
        /**
         * 展示方式（1为一列方式，0为多列方式）
         */
        way: {},
        /**
         * 类型(yyyyMMddhhmmss/S)
         */
        type: {
            default: ''
        },
        /**
         * 开始的时间
         */
        startTime: {},
        /**
         * 结束的时间
         */
        endTime: {},
        /**
         * 输出的格式化样式
         */
        format: {}
    },
    data() {
        return {
            myLists: [],
            myInitMap: {},
            preIndex: 0
        };
    },
    created() {
        let _that = this;
        _that._date = DateTime(_that.options || {});
        _that._initCom();
    },
    watch: {
        typeList() {
            this._initCom();
        }
    },
    computed: {
        /**
         * 拆分样式格式
         * @return {Array}
         */
        typeList() {
            let _fmt = ((this.type || 'yyyyMd') + '')
                .replace(/(y{4}|M{1,2}|d{1,2}|h{1,2}|m{1,2}|s{1,2}|S{1,3})|[^a-zA-Z]+/g, '$1,')
                .replace(/,$/, '').replace(/,,/g, ',');
            return _fmt.split(',');
        }
    },
    mixins: [confirm()],
    methods: {
        /**
         * 选择时的回调
         * @param {Array} list 列表
         * @returns {Object}
         */
        _selectChange(list) {
            const _that = this;
            let res = _that._filterSelect(list);
            return callFn(_that.selectChange, [res]);
        },
        /**
         * 确认
         * @param {Event} evt 事件对象
         */
        _onConfirm(evt) {
            evt = evt || {};
            evt.data = this._filterSelect(evt.data || []);
            this._confirm(evt);
        },
        /**
         * 过滤选中的数据
         * @param {Array} selectList 选中的列表
         * @returns {Date}
         */
        _filterSelect(selectList) {
            let _that = this;
            let _list = selectList.map((item) => {
                return item.value;
            });
            let _order = _that.myOrder.order || [];
            let list = [];
            _that.myLists.forEach((item, index) => {
                list.push(_list[_order[index]]);
            });

            const _fmts = ['yyyy', 'M', 'd', 'h', 'm', 's', 'S'];
            let _preDate = [];
            if (this.preIndex) {
                _preDate = formatDate(this.defaultValue || new Date(), _fmts.slice(0, this.preIndex).join('/')).split('/');
            }
            list = _preDate.concat(list);

            let res = toDate(list.join('/'));
            if (_that.format) {
                let _fmt = [res];
                if (typeof _that.format === 'string') {
                    _fmt.push(_that.format);
                }
                res = formatDate.apply(null, _fmt);
            }
            return res;
        },
        /**
         * 初始化
         */
        _initCom() {
            let _that = this;
            let _typeLen = _that.typeList.length;
            let _index = (_that.way + '' === '1') ? (_typeLen - 1) : 0;
            _that.myLists = (new Array((_typeLen - _index))).fill([]);
            let myOrder = _that.myOrder = _that.getOrder();
            let _order = myOrder.order || [];
            let _options = {};
            if (_that.startTime) {
                _options.startTime = _that.startTime;
            }
            if (_that.endTime) {
                _options.endTime = _that.endTime;
            }
            if (myOrder.missing) {
                // let _date = new Date(); // 如果日期会发生改变的时候，这里取的又是时间的话会出问题
                let _date = this.myValue || new Date(); // 如果日期会发生改变的时候，这里取的又是时间的话会出问题
                let _fmtDate = formatDate(_date, myOrder.missing);
                _options = extend({
                    startTime: _fmtDate,
                    endTime: _fmtDate
                }, _options);
            }
            let key = (!_index) ? _order[0] : 0;
            _that.myLists[key] = _that._getList(myOrder[_order[_index]], _options, true);
            _that.myInitMap[key] = true;
        },
        /**
         * 获取排序map
         * @return {Object}
         */
        getOrder () {
            let _that = this;
            let _types = ['year', 'month', 'date', 'hour', 'minu', 'sec', 'ms'];
            let _typeFmt = {
                'y': 'year',
                'M': 'month',
                'd': 'date',
                'h': 'hour',
                'm': 'minu',
                's': 'sec',
                'S': 'ms',
                'year': 'yyyy',
                'month': 'MM',
                'date': 'dd',
                'hour': 'hh',
                'minu': 'mm',
                'sec': 'ss',
                'ms': 'S'
            };
            let res = {};
            (_that.typeList || []).forEach((item, index) => {
                let key = ((item || '') + '').slice(0, 1);
                let type = _typeFmt[key];
                res[index] = type;
                res[type] = index;
                res[item] = type;
                res.format = res.format || {};
                res.format[index] = item;
                res.format[type] = item;
                res.format[item] = index;
            });
            let i = 0;
            let preIndex = 0;
            _types.forEach((item, index) => {
                if (i <= 0) {
                    preIndex = index;
                }
                if (res[item] !== undefined) {
                    res.order = res.order || {};
                    res.reverse = res.reverse || {};
                    res.reverse[res[item]] = i;
                    res.order[i] = res[item];
                    i++;
                } else if (i <= 0) {
                    res.missing = (res.missing || '') + _typeFmt[item];
                }
            });
            this.preIndex = preIndex;
            return res;
        },
        /**
         * 联动
         * @param {Object} back 返回的数据
         * @param {Object} options 选项
         * @return {Object}
         */
        // eslint-disable-next-line max-statements
        _filterLinkage(back, options) {
            options = options || {};
            let _that = this;
            let _myOrder = _that.myOrder;
            let _order = _myOrder.order || {};
            let _reverse = _myOrder.reverse || {};
            let res = {};
            let _index = _reverse[back.index];
            let _nextIndex = _index + 1;
            let defIndex = 0;
            let def = _that.defaultValue || [];
            let _checkData = back.data;
            let _len = options.lists && options.lists.length;
            if (back.isInit && _index === 0 && def.length > 0 && def[0] !== _checkData.value) {
                defIndex = getActiveIndex(_order[_index], back.lists, def);
            }
            if (defIndex > 0) { // 设置第一列默认选中项
                res.activeIndexMap = Object.assign({}, back.activeIndexMap);
                res.activeIndexMap[_order[_index]] = defIndex;
            } else if (_len > _nextIndex) {
                let myIndex = _order[_nextIndex];
                let _nextData = getStartAndEnd(back.selectList || [], _nextIndex);
                let _cList = back.lists[myIndex];
                if (!_cList || !_cList.length || _nextData.start !== _cList[0].data || _nextData.end !== _cList[_cList.length - 1].data) {
                    res.lists = back.lists.slice(0);
                    res.lists[myIndex] = _that._getList(_myOrder[myIndex], _nextData);
                }
                if (!back.initMap[myIndex]) {
                    res.initMap = extend({}, back.initMap);
                    res.initMap[myIndex] = true;
                    if (def[myIndex]) {
                        res.activeIndexMap = extend({}, back.activeIndexMap);
                        res.activeIndexMap[myIndex] = getActiveIndex(myIndex, res.lists, def);
                    }
                } else if (_that.isResetIndex && back.activeIndexMap[myIndex] !== 0) {
                    res.activeIndexMap = extend({}, back.activeIndexMap);
                    res.activeIndexMap[myIndex] = 0;
                }
            } else {
                return callFn(_that.filterLinkage || res, [res, back, options]);
            }
            if (!res.activeIndexMap && !res.lists) {
                res = this._filterLinkage(Object.assign({}, back, {
                    index: _order[_nextIndex]
                }), options);
            }
            return callFn(_that.filterLinkage || res, [res, back, options]);
            /**
             * 获取开始和结束时间
             * @param {Array} selectList 选中列表
             * @param {Number} endIndex 结束的索引
             * @returns {Object}
             */
            function getStartAndEnd(selectList, endIndex) {
                let _typeLen = _that.typeList.length;
                let _startIndex = (_that.way + '' === '1') ? (_typeLen - 1) : 0;
                let _startItem = selectList[_order[_startIndex]];
                let _list = selectList.map((item) => {
                    return item.value;
                });
                let list = [];
                _that.myLists.every((item, index) => {
                    if (index >= endIndex) {
                        return false;
                    }
                    list.push(_list[_order[index]]);
                    return true;
                });
                let _fmts = ['yyyy', 'M', 'd', 'h', 'm', 's', 'S'];
                let _preDate = [];
                if (_that.preIndex) {
                    _preDate = formatDate(_that.defaultValue || new Date(), _fmts.slice(0, _that.preIndex).join('/')).split('/');
                }
                list = _preDate.concat(list);

                let _start = toDate(list.join('/'));
                let _end = toDate(list.join('/'), true);
                let _fmt = _fmts.slice(0, _that.preIndex + endIndex + 1).join('/');
                let _start1 = toDate(formatDate(_startItem.startTime, _fmt));
                let _end1 = toDate(formatDate(_startItem.endTime, _fmt), true);
                if (_start.getTime() < _start1.getTime()) {
                    _start = _start1;
                }
                if (_end.getTime() > _end1.getTime()) {
                    _end = _end1;
                }
                return {
                    startTime: _start,
                    endTime: _end,
                    start: parseInt(formatDate(_start, _fmts[endIndex]), 10),
                    end: parseInt(formatDate(_end, _fmts[endIndex]), 10)
                };
            }
            /**
            * 获取索引号
            * @param {*} cIndex 当前列表的索引
            * @param {Array} list 列表
            * @param {Array} _def 默认值
            * @returns {Number}
            */
            function getActiveIndex(cIndex, list, _def) {
                let defName = _def && _def[cIndex];
                if (defName && list && list.length > 0) {
                    let activeIndex = list[cIndex].findIndex((item) => {
                        if (item instanceof Object) {
                            return item.value === defName || item.text === defName;
                        }
                        return item === defName;
                    });
                    return Math.max(activeIndex, 0);
                }
            }
        },
        /**
         * 获取列表
         * @param {String} type 类型
         * @param {Object} options 选项
         * @param {boolean} flag 是否需要Date对象
         * @returns {Array}
         */
        _getList(type, options, flag) {
            let _that = this;
            let _date = _that._date;
            let _myOrder = _that.myOrder;
            let _format = _myOrder.format || {};
            let _fmt = _that.way + '' === '1' ? (_that.type || 'yyyyMd') : _format[type];
            return (_date && _date.genList(type, options, (back) => {
                if (!back) {
                    return;
                }
                let _text = formatDate(back.startTime, _fmt);
                let _res = (flag && back) || {};
                _res = Object.assign(_res || {}, {
                    text: _text,
                    value: _text,
                    data: parseInt(formatDate(back.startTime, _format[type]), 10)
                });
                return _res;
            })) || [];
        }
    }
};
</script>
