'use strict';

((factory) => {
    if (typeof module !== 'undefined') {
        const scMathUtil = require('./scMathUtil').getUtil();
        module.exports = factory(scMathUtil);
    } else {
        window.calculateUtil = factory(scMathUtil);
    }
})((scMathUtil) => {
    function standar(exp) {
        //去空格
        exp = exp.replace(/\s/g, '');
        //（ to (
        exp = exp.replace(/（/g, '(');
        //）to )
        exp = exp.replace(/）/g, ')');
        //，to ,
        exp = exp.replace(/，/g, ',');
        //f to F
        exp = exp.replace(new RegExp('f', 'g'), 'F');
        return exp;
    }

    /**
     * 获取累进办法计算的金额
     * @param {Number} baseFee - 基准金额
     * @param {String} name - 使用累进计算的基数名称（需要与累进库中的名称匹配）
     * @param {Array} progressiveData - 项目的累进数据（property.progressiveInterval）
     * @param {Number} decimal - 精度
     * @param {Object} deficiency - 不足处理映射 @example: {'路线工程监理费': 20000 } // 不足2万按2万
     * @return {Number}
     */
    function getProgressiveFee(baseFee, name, progressiveData, decimal, deficiency) {
        if (!progressiveData) {
            throw '该项目不存在累进区间数据';
        }
        //根据基数名称匹配累进库数据,标准化以免(（)）等不同导致不匹配
        const matchProgressiveData = progressiveData.find(item => standar(item.name) === standar(name));
        if (!matchProgressiveData) {
            throw `计算基数{${name}}不存在累进区间数据`;
        }
        // 将原始数据转换成方便处理的数据：[{feeRate: xx, min: 0, max: 200, minOpr: '(', maxOpr: ']'}]
        const progression = matchProgressiveData.progression.map(item => {
            // item.interval内容： eg (0,200]、[300,500) [1000,+)....
            const interval = standar(item.interval);
            // ( => 大于 [ => 大于等于 ) => 小于 ] => 小于等于
            const minReg = /([\(\[])(\d+)/;
            const minMatch = minReg.exec(interval);
            if (!minMatch || !minMatch[1] || !minMatch[2]) {
                throw `计算基数{${name}}累进区间数据错误`;
            }
            const minOpr = minMatch[1];
            // 后台数据单位为万元，这里转为为元
            const min = parseFloat(minMatch[2]) * 10000;
            const maxReg = /[\,，]([\d\+]+)([\)\]])/;
            const maxMatch = maxReg.exec(interval);
            if (!maxMatch || !maxMatch[1] || !maxMatch[2]) {
                throw `计算基数{${name}}累进区间数据错误`;
            }
            const max = maxMatch[1] === '+' ? 'infinity' : parseFloat(maxMatch[1]) * 10000;
            const maxOpr = maxMatch[2];
            return {
                feeRate: item.feeRate,
                min,
                minOpr,
                max,
                maxOpr
            }
        });
        progression.sort((a, b) => a.min - b.min);
        // 基数所在区间
        const withinData = progression.find(item => {
            const oprMiddle = item.max === 'infinity' ? '+' : '';
            const oprLink = item.minOpr + oprMiddle + item.maxOpr;
            switch (oprLink) {
                case '()':
                    return baseFee > item.min && baseFee < item.max;
                case '(]':
                    return baseFee > item.min && baseFee <= item.max;
                case '[)':
                    return baseFee >= item.min && baseFee < item.max;
                case '[]':
                    return baseFee >= item.min && baseFee <= item.max;
                case '(+)':
                case '(+]':
                    return baseFee > item.min;
                case '[+)':
                case '[+]':
                    return baseFee >= item.min;
                default:
                    return false;
            }
        });
        if (!withinData) {
            return 0;
        }
        // 累进计算
        let fee = 0;
        //累进之前的区间
        for (let i = 0; i < progression.indexOf(withinData); i++) {
            const perData = progression[i];
            fee += (perData.max - perData.min) * perData.feeRate * 0.01;
        }
        //累进所在区间
        fee = scMathUtil.roundForObj(fee + (baseFee - withinData.min) * withinData.feeRate * 0.01, decimal);
        // 不足处理
        const deficiencyFee = deficiency && deficiency[name] || 0;
        return deficiencyFee
            ? fee > 0 && fee < deficiencyFee
                ? deficiencyFee
                : fee
            : fee;
    }

    /**
     * 该基数包含的累进基数
     * @param {String} calcBase - 计算基数
     * @param {Array} progression - 累进基数名称数组
     * @return {Array}
     */
    function getProgressive(calcBase, progression) {
        if (typeof calcBase !== 'string' || !progression) {
            return [];
        }
        const reg = /{[^}]+}/g;
        const matched = calcBase.match(reg);
        if (!matched) {
            return [];
        }
        return matched
            .filter(mStr => progression.some(pStr => `{${pStr}}` === mStr))
            .map(mStr => mStr.replace(/[{}]/g, ''));
    }

    /**
     * 该基数是否含有累进基数
     * @param {String} calcBase - 计算基数
     * @param {Array} progression - 累进基数名称数组
     * @return {Boolean}
     */
    function isProgressive(calcBase, progression) {
        const progressiveBase = getProgressive(calcBase, progression);
        return !!progressiveBase.length;
    }

    return {
        getProgressiveFee,
        isProgressive,
        getProgressive,
    };
});