import classNames from './classNames';
import eventsMixin from './eventsMixin';
const DEFAULT_TRIGGER = 'onClick';
const CELL_NAME = '../cell/index';
const FIELD_NAME = '../field/index';
const defaultToolbar = {
    title: '请选择',
    cancelText: '取消',
    confirmText: '确定'
};
const defaultEvents = {
    onChange() {},
    onConfirm() {},
    onCancel() {},
    onVisibleChange() {},
    onValueChange() {}
};
const defaultPlatformProps = {
    labelPropName: 'label',
    format(values, props) {
        return Array.isArray(values.displayValue) ? values.displayValue.join(',') : values.displayValue;
    }
};
const defaultFieldNames = {
    label: 'label',
    value: 'value',
    children: 'children'
};
export default function popupMixin(selector = '#wux-picker', platformProps = defaultPlatformProps) {
    return {
        data() {
            return {
                mounted: false,
                popupVisible: false,
                inputValue: []
            };
        },
        mixins: [
            eventsMixin({
                defaultEvents
            })
        ],
        props: {
            toolbar: {
                type: Object,
                value: defaultToolbar
            },
            trigger: {
                type: String,
                value: DEFAULT_TRIGGER
            },
            defaultVisible: {
                type: Boolean,
                value: false
            },
            visible: {
                type: Boolean,
                value: false
            },
            controlled: {
                type: Boolean,
                value: false
            },
            disabled: {
                type: Boolean,
                value: false
            }
        },
        methods: {
            /**
             * 设置组件显示或隐藏
             */
            setVisibleState(popupVisible, callback = () => {}) {
                if (this.popupVisible !== popupVisible) {
                    const params = {
                        mounted: true,
                        inputValue: this.value,
                        // forceUpdate
                        popupVisible
                    };
                    this.setData(
                        popupVisible
                            ? params
                            : {
                                  popupVisible
                              },
                        () => {
                            // collect field component & forceUpdate
                            if (popupVisible && this.hasFieldDecorator) {
                                const field = this.getFieldElem();
                                if (field) {
                                    field.changeValue(field.data.value);
                                }
                            }
                            callback();
                        }
                    );
                }
            },
            /**
             * 触发 visibleChange 事件
             */
            fireVisibleChange(popupVisible) {
                if (this.popupVisible !== popupVisible) {
                    if (!this.controlled) {
                        this.setVisibleState(popupVisible);
                    }
                    this.setScrollValue(undefined);
                    this.$emit('visibleChange', {
                        detail: {
                            visible: popupVisible
                        }
                    });
                }
            },
            /**
             * 打开
             */
            open() {
                this.fireVisibleChange(true);
            },
            /**
             * 关闭
             */
            close(callback) {
                if (typeof callback === 'function') {
                    const values = this.getPickerValue(this.scrollValue || this.inputValue);
                    callback.call(this, this.formatPickerValue(values));
                }
                this.fireVisibleChange(false);
            },
            /**
             * 组件关闭时重置其内部数据
             */
            onClosed() {
                this.picker = null;
                this.setData({
                    mounted: false,
                    inputValue: null
                });
            },
            /**
             * 点击确定按钮时的回调函数
             */
            onConfirm() {
                this.close((values) => {
                    this.$emit('change', {
                        detail: values
                    }); // collect field component
                    this.$emit('confirm', {
                        detail: values
                    });
                });
            },
            /**
             * 点击取消按钮时的回调函数
             */
            onCancel() {
                this.close((values) =>
                    this.$emit('cancel', {
                        detail: values
                    })
                );
            },
            /**
             * 每列数据选择变化后的回调函数
             */
            onValueChange(e) {
                if (!this.mounted) {
                    return;
                }
                const { value } = e.detail;
                if (this.cascade) {
                    this.setCasecadeScrollValue(value);
                } else {
                    this.setScrollValue(value);
                }
                this.updated(value, true);
                this.$emit('valueChange', {
                    detail: this.formatPickerValue(e.detail)
                });
            },
            /**
             * 获取当前 picker 的值
             */
            getPickerValue(value = this.inputValue) {
                this.picker = this.picker || this.zpSelectComponent(selector);
                return this.picker && this.picker.getValue(value);
            },
            /**
             * 格式化 picker 返回值
             */
            formatPickerValue(values) {
                return {
                    ...values,
                    [platformProps.labelPropName]: platformProps.format(values, this)
                };
            },
            /**
             * 获取 field 父元素
             */
            getFieldElem() {
                return (this.field = this.field || this.getRelationNodes(FIELD_NAME)[0]);
            },
            /**
             * 设置子元素 props
             */
            setChildProps() {
                if (this.disabled) {
                    return;
                }
                const elements = this.getRelationNodes(CELL_NAME);
                const { trigger = DEFAULT_TRIGGER } = this;
                if (elements.length > 0) {
                    elements.forEach((inputElem) => {
                        const { inputEvents } = inputElem.data;
                        const oriInputEvents = inputElem.data.oriInputEvents || {
                            ...inputEvents
                        };
                        inputEvents[trigger] = (...args) => {
                            if (oriInputEvents && oriInputEvents[trigger]) {
                                oriInputEvents[trigger](...args);
                            }
                            this.onTriggerClick();
                        };
                        inputElem.setData({
                            oriInputEvents,
                            inputEvents
                        });
                    });
                }
            },
            /**
             * 触发事件
             */
            onTriggerClick() {
                this.fireVisibleChange(!this.popupVisible);
            },
            /**
             * 阻止移动触摸
             */
            noop() {},
            /**
             * 更新值
             */
            updated(inputValue, isForce) {
                if (!this.hasFieldDecorator || isForce) {
                    if (this.inputValue !== inputValue) {
                        this.setData({
                            inputValue
                        });
                    }
                }
            },
            /**
             * 记录每列数据的变化值
             */
            setScrollValue(value) {
                this.scrollValue = value;
            },
            /**
             * 记录每列数据的变化值 - 针对于级联
             */
            setCasecadeScrollValue(value) {
                if (value && this.scrollValue) {
                    const length = this.scrollValue.length;
                    if (length === value.length && this.scrollValue[length - 1] === value[length - 1]) {
                        return;
                    }
                }
                this.setScrollValue(value);
            }
        },
        lifetimes: {
            ready() {
                const { defaultVisible, visible, controlled, value } = this;
                const popupVisible = controlled ? visible : defaultVisible;

                // 若 defaultFieldNames 存在，则缓存之，并传递给子组件，只生效一次
                if ('defaultFieldNames' in this) {
                    this.setData({
                        fieldNames: Object.assign({}, defaultFieldNames, this.defaultFieldNames)
                    });
                }
                this.mounted = true;
                this.scrollValue = undefined;
                this.setVisibleState(popupVisible);
                this.setChildProps();
            },
            detached() {
                this.mounted = false;
            }
        },
        definitionFilter(defFields) {
            // set default child
            Object.assign((defFields.relations = defFields.relations || {}), {
                [CELL_NAME]: {
                    type: 'child',
                    observer() {
                        this.setChildProps();
                    }
                },
                [FIELD_NAME]: {
                    type: 'ancestor'
                }
            });

            // set default classes
            Object.assign((defFields.computed = defFields.computed || {}), {
                classes: [
                    'prefixCls',
                    function (prefixCls) {
                        const wrap = classNames(prefixCls);
                        const toolbar = `${prefixCls}__toolbar`;
                        const inner = `${prefixCls}__inner`;
                        const cancel = classNames(`${prefixCls}__button`, {
                            [`${prefixCls}__button--cancel`]: true
                        });
                        const confirm = classNames(`${prefixCls}__button`, {
                            [`${prefixCls}__button--confirm`]: true
                        });
                        const hover = `${prefixCls}__button--hover`;
                        const title = `${prefixCls}__title`;
                        return {
                            wrap,
                            toolbar,
                            inner,
                            cancel,
                            confirm,
                            hover,
                            title
                        };
                    }
                ]
            });

            // set default observers
            Object.assign((defFields.observers = defFields.observers || {}), {
                visible(popupVisible) {
                    if (this.controlled) {
                        this.setVisibleState(popupVisible);
                    }
                },
                value(value) {
                    this.updated(value);
                }
            });
        }
    };
}
