/**
 * 校验参数工具
 * 
 */

import { ERRORENUM } from "../config/enum/errorEnum";
import { BizError } from "./bizError";

/**
 * 通过config校验表单参数param
 * 包括类型 String, Number, Boolean, [Number], [Object]
 * 参数是必填
 * 方法会校验表单中存在的多余字段
 * @param name 被调用的方法名
 * @param config 校验配置
 * @param param 需要校验的参数
 * @returns true 无需关注返回
 */
export function eccFormParam(name:string, keyTypeConf:object, param:object) {
    /**校验多余字段 */
    for (let key in param) {
        if (!keyTypeConf[key]) throw new BizError(ERRORENUM.参数错误, name, `多余${key}字段`);
    }

    /**校验已填参数 */
    for (let key in keyTypeConf ) {
        let {type, notMustHave} = keyTypeConf[key];

        let isError = false; //校验是否异常
        let errorStr = "";//异常说明

        let value = param[key];
        let valueType = typeof value;
        
        if ( value == null || value == undefined ) {
            if (!notMustHave) throw new BizError(ERRORENUM.参数错误, name, `缺失${key}字段`);
        } else {
            switch(type) {
                case 'Number':
                    if ( type.toLowerCase() != valueType )  {
                        isError = true;
                    } else {
                        if ((""+param[key]).indexOf('.') > -1) {
                            param[key] = parseInt(`${param[key] *1000}`)/1000;
                        }
                    }
                break;
                case 'String':
                case 'Boolean':
                    if ( type.toLowerCase() != valueType ) isError = true;
                break;
                case '[Number]':
                    if ( !Array.isArray(param[key]) ) isError = true;
                    for (let i =0; i <  param[key].length; i++) {
                        let item = param[key][i];
                        if ( typeof item != 'number' ) {
                            isError = true;
                            errorStr = `${key}应是number型数组其中下标${i}是${typeof item}`;
                        }
                    }
                break;
                case '[Object]':
                    if ( !Array.isArray(param[key]) ) isError = true;
                    for (let i =0; i <  param[key].length; i++) {
                        let item = param[key][i];
                        if ( typeof item != 'object' ) {
                            isError = true;
                            errorStr = `${key}应是object型数组其中下标${i}是${typeof item}`;
                        }
                    }
                break;
                case 'Address':
                    /**地址类型 基本数据类型为数组字符串但是要判断层级关系 */
                    if ( !Array.isArray(param[key]) ) {
                        isError = true;
                        errorStr = `${key}应是数组形`;
                    }
                    if ( param[key].length != 4) {
                        isError = true;
                        errorStr = `${key}超过特定长度4 目前长度 ${param[key].length}`;
                    }
                    for (let i =0; i <  param[key].length; i++) {
                        let item = param[key][i];
                        if ( typeof item != 'string' ) {
                            isError = true;
                            errorStr = `${key}应是string型数组其中下标${i}是${typeof item}`;
                        }
                    }
                    /** 不符合规则的 */
                    let nullIndex = -1;
                    for (let i = 0; i < param[key].length; i++) {
                        if (nullIndex != -1) {//出现过空 第一次出现后的位置 都不能有值
                            if (param[key]) {
                                //做一个特化
                                throw new BizError(ERRORENUM.地址数据不完整, name, `${key} 下标 ${nullIndex} 为空 `);
                            }
                        }
                        if (nullIndex == -1 && !param[key][i]) {
                            /**按顺序第一次赋值 */
                            nullIndex = i;
                        }
                    }
    
                break;
            }
            errorStr = isError && errorStr == "" ? `${key}应该是${type}型 而不是${valueType}`: errorStr;
            if ( isError ) throw new BizError(ERRORENUM.参数校验失败, name, errorStr);
        }

       
    }
    return true;
}


/**
 * 根据conf配置校验请求参数
 * @param conf 配置  
 * @param param 表单  
 * @param skipKeys []不必填的字段
 */
export function eccReqParamater(conf:object, param, skipKeys?) {
    skipKeys = skipKeys || [];

    let skipMap = {};
    skipKeys.forEach(keyName => {
        skipMap[keyName] = 1;
    });

    /**校验多余字段 */
    for (let key in param) {
        if (!conf[key]) throw new BizError(ERRORENUM.参数错误, `多余${key}字段`);
    }

    /**校验必填和缺失字段 */
    for (let key in conf) {
        let confType = conf[key];
        let value = param[key];
        let valueType = typeof value;
        
        if ( value == null || value == undefined ) {
            if (!skipMap[key]) throw new BizError(ERRORENUM.参数错误, `缺失${key}字段`);
        } else {
            let isError = false;
            let errorStr = "";
            switch(confType) {
                case 'Number':
                    if ( confType.toLowerCase() != valueType ) isError = true;
                    else {
                        if ((""+param[key]).indexOf('.') > -1) {
                            param[key] = parseInt(`${param[key] *100}`)/100;
                        }
                    }
                break;
                case 'String':
                case 'Boolean':
                    if ( confType.toLowerCase() != valueType ) isError = true;
                break;
                case '[Number]':
                    if ( !Array.isArray(param[key]) ) isError = true;
                    for (let i =0; i <  param[key].length; i++) {
                        let item = param[key][i];
                        if ( typeof item != 'number' ) {
                            isError = true;
                            errorStr = `${key}应是number型数组其中下标${i}是${typeof item}`;
                        }
                    }
                break;
                case '[Object]':
                    if ( !Array.isArray(param[key]) ) isError = true;
                    for (let i =0; i <  param[key].length; i++) {
                        let item = param[key][i];
                        if ( typeof item != 'object' ) {
                            isError = true;
                            errorStr = `${key}应是object型数组其中下标${i}是${typeof item}`;
                        }
                    }
                break;
                case 'Address':
                    /**地址类型 基本数据类型为数组字符串但是要判断层级关系 */
                    if ( !Array.isArray(param[key]) ) {
                        isError = true;
                        errorStr = `${key}应是数组形`;
                    }
                    if ( param[key].length != 4) {
                        isError = true;
                        errorStr = `${key}超过特定长度4 目前长度 ${param[key].length}`;
                    }
                    for (let i =0; i <  param[key].length; i++) {
                        let item = param[key][i];
                        if ( typeof item != 'string' ) {
                            isError = true;
                            errorStr = `${key}应是string型数组其中下标${i}是${typeof item}`;
                        }
                    }
                    /** 不符合规则的 */
                    let nullIndex = -1;
                    for (let i = 0; i < param[key].length; i++) {
                        if (nullIndex != -1) {//出现过空 第一次出现后的位置 都不能有值
                            if (param[key]) {
                                //做一个特化
                                throw new BizError(ERRORENUM.地址数据不完整, `${key} 下标 ${nullIndex} 为空 `);
                            }
                        }
                        if (nullIndex == -1 && !param[key][i]) {
                            /**按顺序第一次赋值 */
                            nullIndex = i;
                        }
                    }
    
                break;
            }
            errorStr = isError && errorStr == "" ? `${key}应该是${confType}型 而不是${valueType}`: errorStr;
            if (isError) throw new BizError(ERRORENUM.参数错误, errorStr);
        }

    }

    return param;
}