import globalVariable from "../global-variable";
import {PaginationModel} from "../model/pagination.model";
import {CommonUtil} from "../utils/common.util";
import {UFormUtil} from "../utils/u-form.util";
import {LocalStorageUtil} from "../utils/local-storage.util";
import {TabbarUtil} from "../utils/tabbar.util";

/**
 *  mixin的作用是多个组件可以共享数据和方法，在使用mixin的组件中引入后，mixin中的方法和属性也就并入到该组件中，
 * 可以直接使用，在已有的组件数据和方法进行了扩充。引入mixin分全局引用和局部引用。
 * todo 可以代替基类base的功能
 *
 * todo Page页面生命周期函数执行顺序
 * beforeCreate => onLoad => onShow => created => beforeMount => onReady => mounted
 * 刷新数据后
 * beforeUpdate => updated
 *
 * vue 父子组件的生命周期顺序加载渲染过程
 * 父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
 *
 * 子组件更新过程
 * 父beforeUpdate->子beforeUpdate->子updated->父updated
 *
 * 父组件更新过程
 * 父beforeUpdate->父updated
 *
 * 销毁过程
 * 父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
 */
const myMixin = {
    data() {
        return {
            // _self: null,  // todo 不能直接赋值否则u-view框架报错， 当vue作为组件<componentName></componentName>引用时，组件模板页面<template/>中的this为null，这时需要使用_self变量代替。
            uni: uni, // 不这样设置，template页面中不能直接使用（例如：@click="uni.navigateTo({url: 'xxx})"）
            $u: this.$u,  // 不这样设置，template页面中取不到值
            CommonUtil: CommonUtil,  // 不这样设置，template页面中无法直接使用
            TabbarUtil: TabbarUtil,  // 不这样设置，template页面中无法直接使用
            UFormUtil: UFormUtil,  // 不这样设置，template页面中无法直接使用
            globalVariable: globalVariable,  // todo <template/>模板页面中可以直接使用，js中可以直接使用
            pagination: new PaginationModel(),  // 每个组件都是一个新的对象互不影响
            urlParams: {},  // 导航过来的url参数?a=1&b=2 ==> {a: 1, b: 2} <template/>可以直接获取
            objParams: {},  // 导航过来的对象参数 todo 导航过来的是同一个对象，改变内容所有引用的页面将会同时受到影响。 <template/>可以直接获取
            currentRouteUrl: '',
            // 时间控件显示格式：2020-09-22 16:57:38
            pickerFormatDatetime: {
                year: true,
                month: true,
                day: true,
                hour: true,
                minute: true,
                second: true,
            },
            // 时间控件显示格式：2020-09-22
            pickerFormatDate: {
                year: true,
                month: true,
                day: true,
                hour: false,
                minute: false,
                second: false,
            }
        }
    },
    // options 参数为null，当组件使用时不会被调用
    beforeCreate(options) {
        // console.log(`myMixin--------------------------------beforeCreate(${JSON.stringify(options)})--------------------------------`)
        const _self = this;
        // 刷新页面时重新赋值，否则页面会报错。
        if (!globalVariable.token) {
            let token = LocalStorageUtil.getItem("token");
            let userInfo = LocalStorageUtil.getItem("userInfo");
            globalVariable.orderSequenceNumber = null;  // 删除已扫码的餐饮号
            if (token && userInfo) {
                globalVariable.token = token;
                globalVariable.userInfo = userInfo;
            }
        }
    },
    // options页面导航的参数，当组件使用时不会被调用
    onLoad(options) {
        console.log(`myMixin--------------------------------onLoad(options)--------------------------------`, options);
        const _self = this;
        _self.urlParams = options;  // app端没有this.$root.$mp.query参数。
        if (!_self.urlParams) {
            _self.urlParams = {};
        }
        console.log("urlParams------------------------", _self.urlParams);

        if (_self.urlParams && _self.urlParams.q && _self.urlParams.scancode_time) {
            _self.urlParams.url = decodeURIComponent(_self.urlParams.q);
            _self.urlParams = CommonUtil.getUrlParams(_self.urlParams.url);
            _self.urlParams.isScan = "1";  // 是否扫码进入到该页面
            console.log("微信扫码进入小程序结果urlParams------------------------", _self.urlParams);
        }

        // 兼容部分手机机型不能从导航事件中获取objParams问题。
        if (!globalVariable.objParams) {
            globalVariable.objParams = {};
        }
        _self.objParams = globalVariable.objParams;
        console.log("globalVariable.objParams------------------------", _self.objParams);

        const eventChannel = this.getOpenerEventChannel();
        eventChannel.on('objParams', function (data) {
            _self.objParams = data;
            console.log("objParams------------------------", data);
        });

        if (this.validateForm) {
            UFormUtil.init(this.validateForm);
            console.log("validateForm表单对象初始化成功--------------------------------", this.validateForm);
        }
    },
    // options 参数为null，当组件使用时不会被调用
    onShow(options) {
        // console.log(`myMixin--------------------------------onShow(${JSON.stringify(options)})--------------------------------`)
    },
    // options 参数为null，当组件使用时不会被调用
    created(options) {
        // console.log(`myMixin--------------------------------created(${JSON.stringify(options)})--------------------------------`)
    },
    // options 参数为null，当组件使用时不会被调用
    onReady(options) {
        // console.log(`myMixin--------------------------------onReady(${JSON.stringify(options)})--------------------------------`)
        if (this.validateForm && !this.validateForm.controls) {  // todo 当组件使用时onLoad方法不会被调用，所以需要在这里初始化。
            UFormUtil.init(this.validateForm);
            console.log("validateForm表单对象初始化成功--------------------------------", this.validateForm);
        }
        if (this.validateForm && this.validateForm.rules && this.$refs.validateFormRef) {
            this.$refs.validateFormRef.setRules(this.validateForm.rules);
            console.log("validateFormRef表单校验规则初始化成功--------------------------------", this.validateForm);
        }
    },
    // options 参数为null，todo 当组件使用时会被调用
    mounted(options) {
        // console.log(`myMixin--------------------------------mounted(${JSON.stringify(options)})--------------------------------`)
        this._self = this;  // todo 当vue作为组件<componentName></componentName>引用时，组件模板页面<template/>中的this为null，这时需要使用_self变量代替。

        if (this.validateForm && !this.validateForm.controls) {  // todo 当组件使用时onLoad方法不会被调用，所以需要在这里初始化。
            UFormUtil.init(this.validateForm);
            console.log("validateForm表单对象初始化成功--------------------------------", this.validateForm);
        }

        if (this.validateForm && this.validateForm.rules && this.$refs.validateFormRef) {
            this.$refs.validateFormRef.setRules(this.validateForm.rules);
            console.log("validateFormRef表单校验规则初始化成功--------------------------------", this.validateForm);
        }

        // 获取路由数组
        let routes = getCurrentPages();
        if (routes && routes.length) {
            this.currentRouteUrl = routes[routes.length - 1].route;
        }
    },
    methods: {
        /**
         * template页面中使用这种方式才能跳转页面
         * @param url
         * @param urlParams
         * @param objParams 传递对象类型数据给下一个页面，改变内容所有引用的页面将会同时受到影响。
         * 导航：navigateTo(url, urlParams, objParams)，跳转页面的objParams将指向同一个地址，修改将同时受到影响。
         * 导航：navigateTo(url, urlParams, {objParams： objParams}) 跳转页面的objParams对象是一个全新的对象，指向不同的地址。对其修改不影响原对象的值。
         * todo 在<template/>中使用{tbOrder: tbOrder}的方式传值时，将产生一个全新的tbOrder副本，并不是只向原来的tbOrder地址，所以对新的tbOrder修改不会影响原来的tbOrder。
         * todo 在<template/>中使用globalVariable.tempData.tbOrder = tbOrder赋值后globalVariable.tempData.tbOrder不是tbOrder，而是一个全新属性错乱的对象。
         *
         * 所以要传递多个对象并且每个对象始终保持是同一个地址，则需要在js中实现。
         * 例如：@click="test(url, urlParams, obj1, obj2)"
         * test(url, urlParams, obj1, obj2){
         *     this.navigateTo(url, urlParams, {obj1, obj2});
         *     // 或者
         *     this.navigateTo(url, urlParams).then(res=>{
         *         res.eventChannel.emit('objParams', {obj1, obj2});
         *     })
         * }
         */
        navigateTo(url, urlParams, objParams) {

            // 兼容部分手机机型不能从导航事件中获取objParams问题。
            globalVariable.objParams = objParams;

            return new Promise(function (resolve, reject) {
                if (urlParams) {
                    if (url.indexOf("?") === -1) {
                        url = url + "?" + CommonUtil.objectToUrlParams(urlParams);
                    } else {
                        url = url + "&" + CommonUtil.objectToUrlParams(urlParams);
                    }
                }
                uni.navigateTo({
                    url: url,
                    success: function (res) {
                        if (objParams) {
                            // 通过eventChannel向被打开页面传送数据
                            res.eventChannel.emit('objParams', objParams)
                        }
                        resolve(res);
                    }
                })
            });
        },
        /**
         * 刷新数据
         * @param dataList
         */
        doRefresh(dataList) {
            // 清空数据。
            // console.log("myMixin--------------------------------doRefresh()--------------------------------")
            dataList.splice(0, dataList.length);
            this.pagination = new PaginationModel();
            this.$forceUpdate();
            this.$nextTick(() => {
                this.pagination = new PaginationModel();
                this.doInfinite();
            });
        },
        /**
         * 根据componentRef切换底部菜单栏选项
         * @param componentRef
         */
        switchTarBarByComponentRef(componentRef) {
            const _self = this;
            let pages = getCurrentPages();
            console.log(pages);
            pages.forEach((page, index) => {
                if (page.route === 'pages/sub/sub1-tabs/tabs/index') {
                    // h5调用属性和方法可以不用page.$vm，但是微信小程序必须是page.$vm.否则报错。
                    page.$vm.tarbar.forEach((item, index) => {
                        if (item.componentRef === componentRef) {
                            page.$vm.onChangeTabbarTab(index);
                        }
                    });
                }
            });
        }
    }
};

export default myMixin
