/**
 * 界面相关接口
 */
/* globals GLOBAL_OBJECT */
import { callNative, emptyFn, typeCheck, callNativeSync } from './util';

const leftButtonOnClick = {};

const modalProm = Promise.resolve();

export default {
    leftButtonOnClick,
    /**
     * 显示消息提示框
     *
     * @param {object} options
     * @param {string} [options.title=''] 提示的内容
     * @param {string} [options.icon='success'] 图标
     * @param {string} [options.image=''] 自定义图片路径
     * @param {number} [options.duration=1500] 提示的延迟时间
     * @param {boolean} [options.mask=false] 是否显示透明蒙层
     * @param {function} [options.success=emptyFn] 成功回调
     * @param {function} [options.fail=emptyFn] 失败回调
     */
    showToast({
        title = '',
        icon = 'success',
        image = '',
        duration = 1500,
        mask = false,
        success = emptyFn,
        fail = emptyFn,
        complete = emptyFn
    } = {}) {
        callNative('showToast', { title, icon, image, duration, mask, success, fail, complete });
    },
    /**
     * 隐藏消息提示框
     *
     * @param {object} options
     * @param {function} options.success 成功回调
     * @param {function} options.fail 失败回调
     */
    hideToast(options = {}) {
        callNative('hideToast', options);
    },
    /**
     * 显示 loading 提示框, 需主动调用 bl.hideLoading 才能关闭提示框
     *
     * @param {object} options
     * @param {string} [options.title='']  提示的内容
     * @param {boolean} [options.mask=false]  是否显示透明蒙层，防止触摸穿透
     * @param {function} [options.success=emptyFn]  接口调用成功的回调函数
     * @param {function} [options.fail=emptyFn]  接口调用失败的回调函数
     */
    showLoading({
        title = '',
        mask = false,
        success = emptyFn,
        fail = emptyFn,
        complete = emptyFn,
    } = {}) {
        callNative('showLoading', { title, mask: !!mask, success, fail, complete }, { title: 'String' });
    },
    /**
     * 隐藏 loading 提示框
     *
     * @param {object} options
     * @param {function} options.success 成功回调
     * @param {function} options.fail 失败回调
     */
    hideLoading(options = {}) {
        setTimeout(() => {
            callNative('hideLoading', options);
        }, 0);
    },
    /**
     * 显示模态对话框
     *
     * @param {object} options
     * @param {string} [options.title=''] 提示的标题
     * @param {string} [options.content=''] 提示的内容
     * @param {boolean} [options.showCancel=true] 是否显示取消按钮
     * @param {string} [options.cancelText='取消'] 取消按钮的文字，最多 4 个字符
     * @param {string} [options.cancelColor='#000000'] 取消按钮的文字颜色，必须是 16 进制格式的颜色字符串
     * @param {string} [options.confirmText='确定'] 确认按钮的文字，最多 4 个字符
     * @param {string} [options.confirmColor='#ff5687'] 确认按钮的文字颜色，必须是 16 进制格式的颜色字符串
     * @param {function} [options.success=emptyFn] 接口调用成功的回调函数
     * @param {function} [options.fail=emptyFn] 接口调用失败的回调函数
     */
    showModal({
        title = '',
        content = '',
        showCancel = true,
        cancelText = '取消',
        cancelColor = '',
        confirmText = '确定',
        confirmColor = '',
        success = emptyFn,
        fail = emptyFn,
        complete = emptyFn
    } = {}) {
        modalProm.then(() => new Promise(resolve => {
            const options = {
                title,
                content,
                showCancel: !!showCancel,
                cancelText,
                cancelColor,
                confirmText,
                confirmColor,
                success,
                fail,
                complete: function() {
                    let result;
                    if (typeof complete == 'function') {
                        result = complete.apply(null, arguments);
                    }
                    resolve(result);
                }
            };
            callNative('showModal', options, {
                title: 'String',
                content: 'String',
                cancelText: 'String',
                cancelColor: 'String',
                confirmText: 'String',
                confirmColor: 'String',
            });
        }));
    },
    /**
     * 展示ActionSheet
     *
     * @param {object} options
     * @param {string[]} options.itemList 按钮的文字数组，数组长度最大为 6
     * @param {string} [options.itemColor='#000000'] 按钮的文字颜色
     * @param {function} [options.success=emptyFn] 接口调用成功的回调函数
     * @param {function} [options.fail=emptyFn] 接口调用失败的回调函数
     * @returns
     */
    showActionSheet({
        itemList,
        itemColor = '',
        success = emptyFn,
        fail = emptyFn,
        complete = emptyFn
    } = {}) {
        let failFn = typeof fail === 'function' ? fail : emptyFn;

        if (Object.prototype.toString.call(itemList) !== '[object Array]') {
            failFn({ errMsg: 'showActionSheet:fail parameter error: parameter.itemList should be Array' });
            return;
        }

        if (itemList.length < 1) {
            failFn({ errMsg: 'showActionSheet:fail parameter error: parameter.itemList should have at least 1 item' });
            return;
        }

        if (itemList.length > 6) {
            failFn({ errMsg: 'showActionSheet:fail parameter error: itemList should not be large than 6' });
            return;
        }

        for (let i = 0; i < itemList.length; i++) {
            const element = itemList[i];
            let result = typeCheck(element, 'String');
            if (result) {
                failFn({ errMsg: `showActionSheet:fail parameter error: itemList[${i}] should be String instead of ${result}` });
                return;
            }
        }

        const options = {
            itemList,
            itemColor,
            success,
            fail,
            complete
        };

        callNative('showActionSheet', options);
    },
    /**
     * 将页面滚动到目标位置
     *
     * @param {Object} options
     * @param {Number} options.scrollTop 动到页面的目标位置（单位px）
     * @param {Number} options.duration 滚动动画的时长，默认300ms，单位 ms
     * @param {function} [options.success=emptyFn] 接口调用成功的回调函数
     * @param {function} [options.fail=emptyFn] 接口调用失败的回调函数
     */
    pageScrollTo({
        scrollTop,
        duration = 300,
        success = emptyFn,
        fail = emptyFn,
        complete = emptyFn
    } = {}) {
        const options = {
            scrollTop,
            duration,
            success,
            fail,
            complete
        };

        // ios 客户端方案有问题，滚动页面会导致fixed布局丢失，前端擦屁股兼容
        if (bl.getSystemInfoSync().platform.toLocaleLowerCase() === 'ios') {
            const successFn = typeof options.success === 'function' ? options.success : emptyFn;
            const failFn = typeof options.fail === 'function' ? options.fail : emptyFn;
            const completeFn = typeof options.complete === 'function' ? options.complete : emptyFn;

            const callbackFn = (result) => {
                let _output = {}
                if (result.code === 0) {
                    _output = { errMsg: `pageScrollTo:ok` }
                    successFn(_output);
                    completeFn(_output);
                } else {
                    let errInfo = result.msg;
                    let output = {};

                    output.errMsg = `pageScrollTo:fail ${errInfo}`;

                    failFn(output);
                    completeFn(output);
                }
            };

            let _callbackId = Service.getUid();
            Service.callbacks[_callbackId] = callbackFn;
            Service.postMessage(JSON.stringify({
                type: 'api-render',
                event: 'pageScrollTo',
                data: {
                    scrollTop,
                    callbackId: _callbackId
                },
            }), global.__biliCacheData.getCurrentPageId())
        } else {
            callNative('pageScrollTo', options, { scrollTop: 'Number' });
        }
    },
    /**
     * 开始下拉刷新提示框
     *
     * @param {object} options
     * @param {function} options.success 成功回调
     * @param {function} options.fail 失败回调
     */
    startPullDownRefresh(options = {}) {
        callNative('startPullDownRefresh', options);
    },
    /**
     * 结束下拉刷新提示框
     *
     * @param {object} options
     * @param {function} options.success 成功回调
     * @param {function} options.fail 失败回调
     */
    stopPullDownRefresh(options = {}) {
        callNative('stopPullDownRefresh', options);
    },
    /**
     * 设置titleBar标题
     *
     * @param {Object} options
     * @param {String} options.title 设置的标题
     * @param {Function} [options.success=emptyFn]  成功回调
     * @param {Function} [options.fail=emptyFn]  失败回调
     */
    setNavigationBarTitle(options = {}) {
        callNative('setNavigationBarTitle', options, { title: 'String' });
    },
    /**
     * 设置导航栏style
     *
     * @param {Object} options
     * @param {String} options.style 设置的颜色
     * @param {Function} [options.success=emptyFn]  成功回调
     * @param {Function} [options.fail=emptyFn]  失败回调
     */
    setStatusBarStyle(options = {}) {
        callNative('setStatusBarStyle', options);
    },

    /**
     * 设置导航栏颜色
     *
     * @param {Object} options
     * @param {Hex Color} options.frontColor 设置的颜色
     * @param {Hex Color} options.backgroundColor 设置的颜色
     * @param {String} options.statusStyle 设置的颜色
     * @param {Function} [options.success=emptyFn]  成功回调
     * @param {Function} [options.fail=emptyFn]  失败回调
     * @param {Function} [options.complete=emptyFn]  失败回调
     */
    setNavigationBarColor(options) {
        callNative('setNavigationBarColor', options, {frontColor: 'String', backgroundColor: 'String'});
    },
    /**
     * 设置导航栏左边自定义按钮
     *
     * @param {Object} options
     * @param {String} options.iconPath 按钮icon的路径
     * @param {Function} [options.onClick=emptyFn]  点击按钮的回调
     * @param {Function} [options.success=emptyFn]  成功回调
     * @param {Function} [options.fail=emptyFn]  失败回调
     */
    showNavigationLeftButton({
        iconPath,
        onClick = emptyFn,
        success = emptyFn,
        fail = emptyFn
    }) {
        const pageId = global.__biliCacheData.getCurrentPageId();
        const pageVm = bl.getCurrentPages()[0];

        if (pageVm.$options.hasNavigationBar) {
            leftButtonOnClick[pageId] = onClick;

            callNative('showNavigationLeftButton', {
                pageId,
                iconPath,
                success,
                fail
            }, {
                iconPath: 'String'
            });
        } else {
            fail({
                errMsg: 'not support when hasNavigationBar\'s value is false'
            });
        }
    },
    /**
     * 隐藏导航栏左边自定义按钮
     *
     * @param {Object} options
     * @param {Function} [options.success=emptyFn]  成功回调
     * @param {Function} [options.fail=emptyFn]  失败回调
     */
    hideNavigationLeftButton(options = {}) {
        const pageId = global.__biliCacheData.getCurrentPageId();
        const pageVm = bl.getCurrentPages()[0];

        if (pageVm.$options.hasNavigationBar) {
            callNative('hideNavigationLeftButton', Object.assign({ pageId }, options));
        } else {
            options.fail && options.fail({
                errMsg: 'not support when hasNavigationBar\'s value is false'
            });
        }
    },
    getMenuButtonBoundingClientRect() {
        const systemInfo = callNativeSync('getSystemInfoSync').data;
        const result = callNativeSync('getMenuButtonBoundingClientRect').data;

        if (systemInfo.platform === 'ios' && systemInfo.SDKVersion >= '2.4.0') {
            result.right = result.left + result.width;
            result.bottom = result.top + result.height;
            return result;
        }

        return result;
    },
    /**
     * 自定义窗口背景色
     *
     * @param {Object} options
     * @param {String} options.backgroundColor 窗口的背景色
     * @param {String} options.backgroundColorTop 顶部窗口的背景色
     * @param {String} options.backgroundColorBottom 底部窗口的背景色
     * @param {Function} [options.success=emptyFn]  成功回调
     * @param {Function} [options.fail=emptyFn]  失败回调
     */
    setBackgroundColor({
        backgroundColor,
        backgroundColorTop,
        backgroundColorBottom,
        success = emptyFn,
        fail = emptyFn,
        complete = emptyFn
    } = {}) {
        const options = {
            backgroundColor,
            backgroundColorTop,
            backgroundColorBottom,
            success,
            fail,
            complete
        };

        callNative('setBackgroundColor', options);
    }
};
