//out 前置逻辑
import { BizError } from "../util/bizError";
import { separateDataAndUint } from "./tool";

/**
 * stringListPackage 打包验证并返回 getStringOut 需要的格式
 * @param dataList [{key, value},{}]
 * @param keyName 
 * @returns ["","",""]
 */
export function stringListPackage(dataList, keyName = "value") {
    let result = [];
    dataList.forEach(info => {
        result.push(info[keyName]);
    });
    
    return result;
}

/**
 * onceYBarChartPackage  打包验证并返回 getOnceYBarChartOut 需要的格式
 * @param dataList [{name:"", data:[{key, value}...] }]
 * @param inYUnit y轴单位
 * @param inXUnit x轴单位
 * @returns {xUnit:x轴单位, yUnit:y单位, dataInfo:{"图表名称":[{key:"数据key", value:"数据值", unit:"单位" }, {key:"数据key", value:"数据值", unit:"单位" } ]    }   }
 */
export function onceYBarChartPackage(inDataList, inYUnit, inXUnit="") {
    let dataInfo = {};
    const InYUnitIsNull = !inYUnit;

    let checkingDataHaveUnitMap = {};
    let yUnit = "";

    inDataList.forEach(info => {
        let name = info.name;
        let data = info.data;
        checkingError({name, data}, errorEnum.必要参数);

        let onceDataList = [];
        //判空 去重
        let distinctMap = {};
        //验证工作
        data.forEach(subInfo => {
            let key = subInfo.key;
            let value = subInfo.value;
            checkingError({name, key}, errorEnum.数据key是否为空);
            checkingError({name, value}, errorEnum.数据value是否为数值);
            checkingError({name, distinctMap, key}, errorEnum.barChart中x轴的key重复出现);
            distinctMap[key] = 1;

            let {dataNum, dataUnit} = separateDataAndUint(value);
            checkingDataHaveUnitMap[dataUnit] = 1;
            onceDataList.push({key, value:dataNum, unit:dataUnit|| "" });
        });

        dataInfo[name] = onceDataList;
    });

    let dataUnitList = Object.keys(checkingDataHaveUnitMap);
    let dataHaveUnitCount = dataUnitList.length;
    if (!dataHaveUnitCount && InYUnitIsNull ) {
        //todo 这里可以加逻辑 挖个坑 可以读取表格里面的所有单位取出现最多的
    } else if(dataHaveUnitCount> 1) throw new BizError(`在 onceYBarChartPackage 中 单个y轴的柱状图中出现多个单位:${JSON.stringify(dataUnitList)}`);
    else {
        yUnit = dataUnitList[0] || inYUnit;
        for (let key in dataInfo) {
            dataInfo[key].forEach(info => {
                info.unit = yUnit;
            });
        }
    }
    
    return {xUnit:inXUnit, yUnit, dataInfo };
}


/**
 * doubleYBarCharPackage  打包验证并返回 getDoubleYBarChartOut 需要的格式
 * @param inLeftYUnit
 * @param inRightYUnit
 * @param data [{name:"", data:[{key, value}...] }]
 * @param rightNameList  ["name", name] 右边y轴的名称
 * @returns {xUnit:x轴单位, leftYUnit:左边y单位, rightYUnit:右边y单位 dataInfo:{"图表名称":{from:"left", subList:[{key:"数据key", value:"数据值", unit:"单位" }, {key:"数据key", value:"数据值", unit:"单位" } ]}    }   }
 */
export function doubleYBarCharPackage(data, rightNameList, inLeftYUnit, inRightYUnit, xUnit = "") {
    let leftAndRightDistinctMap = {};//比对两种图表名称有没有冲突
    let dataInfo = {};

    let leftUnitDistinctMap = {};
    let rightUnitDistinctMap = {};

    function checkOnceData(subFunCheckingList, dataType) {
        subFunCheckingList.forEach(info => {
            let name = info.name;
            let data = info.data;
            checkingError({name, data}, errorEnum.必要参数);
            if (leftAndRightDistinctMap[name]) throw new BizError(`在 doubleYBarCharPackage 中leftYData 和 rightYData 重复出现了 ${name}`);
            leftAndRightDistinctMap[name] = 1;
    
            let subList = [];
            let distinctMap = {};
            data.forEach(subInfo => {
                let key = subInfo.key;
                let value = subInfo.value;
                checkingError({name, key}, errorEnum.数据key是否为空);
                checkingError({name, value}, errorEnum.数据value是否为数值);
                checkingError({name, distinctMap, key}, errorEnum.barChart中x轴的key重复出现);
                distinctMap[key] = 1;
    
                let {dataNum, dataUnit} = separateDataAndUint(value);

                if (dataUnit) dataType == "left" ? leftUnitDistinctMap[dataUnit] = 1 : rightUnitDistinctMap[dataUnit] = 1;

                subList.push({key, value:dataNum, unit:dataUnit || ""});
    
            });
            dataInfo[name] = {from:dataType, subList};
        });
    }

    let leftYData = [];
    let rightYData = [];
    data.forEach(info => {
        let {name} = info;
        if (rightNameList.indexOf(name) > -1 ) rightYData.push(info);
        else leftYData.push(info);
    });

    checkOnceData(leftYData, "left");
    checkOnceData(rightYData, "right");

    let leftUnitList = Object.keys(leftUnitDistinctMap);
    let leftUnitCount = leftUnitList.length;
    let rightUnitList = Object.keys(rightUnitDistinctMap);
    let rightUnitCount = rightUnitList.length;
    if (leftUnitCount > 1)  throw new BizError(`在 onceYBarChartPackage 中 双y轴的柱状图中 leftData数据中出现了多个单位:${JSON.stringify(leftUnitList)}`);
    if (rightUnitCount > 1)  throw new BizError(`在 onceYBarChartPackage 中 双y轴的柱状图中 rightData数据中出现多个单位:${JSON.stringify(rightUnitList)}`);
    
    let leftYUnit = leftUnitList[0] || inLeftYUnit;
    let rightYUnit = rightUnitList[0] || inRightYUnit;
    
    for (let key in dataInfo) {
        let {from } = dataInfo[key];
        dataInfo[key].subList.forEach(info => {
            if (from == "left") info.unit = leftYUnit;
            else info.unit = rightYUnit;
        });
    }
    
    return {xUnit, leftYUnit, rightYUnit, dataInfo };
}


/**
 * tablePackage 获得 getTableOut 需要的数据
 * @titleList ["","","",""]
 * @param data [[a,b,c],[a,b,c],[a,b,c],[a,b,c]]
 * @returns {titleList:[], dataList:[{a,b,c},{a,b,c},{a,b,c}] }
 */
export function tablePackage(titleList, data) {
    var aForZkeyList = [];
    for(var i = 65; i < 91; i++){
        aForZkeyList.push(String.fromCharCode(i));
    }

    //验证长度
    let dataMaxLenght = 0;

    let dataList = [];
    data.forEach(subDataList => {
        let onceData = {};
        subDataList.forEach((info, index) => {
            let key = aForZkeyList[index];
            onceData[key] = info || "";
        });
        dataMaxLenght = Math.max(dataMaxLenght, subDataList.length);
        dataList.push(onceData);
    });

    if (titleList.length < dataMaxLenght) throw new BizError( `在 tablePackage 中 titleList长度比单个data最大长度小  titleList长度 ${titleList.length} 单个数据个数 ${dataMaxLenght}"`);

    return {titleList, dataList};
}

/**
 * keyValuePackage 将返回 getKeyValueOut 所需要的数据格式
 * @param dataList [{key, value}]
 * @returns [{key:"", value:"", unit:""}]
 */
export function keyValuePackage(dataList) {
    let data = [];
    dataList.forEach(info => {
        let key = info.key;
        let value = info.value;
        checkingError({value, key}, errorEnum.数据key是否为空);
        let {dataNum, dataUnit} = separateDataAndUint(value);
        let analysisValue;
        let analysisUnit;
        if (isNaN(dataNum) || dataUnit == value){
            analysisValue = value;
            analysisUnit = "";
        } else {
            analysisValue = dataNum;
            analysisUnit = dataUnit;
        }
        data.push({key, value:analysisValue, unit:analysisUnit });
    });

    return data;
}


/**
 * objectListPackage 将返回 getObjectListOut  所需要的数据格式
 * @param dataList [{key...}]
 * @returns  [{key...}]
 */
export function objectListPackage(dataList) {
    let data = [];
    dataList.forEach(info => {
        let addInfo = {};
        for (let key in info) {
            checkingError({key, value:info[key]}, errorEnum.值为undefined或null);
            addInfo[key] == info;
        }
        data.push(addInfo);
    });
    return data;
}


/**
 * rankPackage 将返回 getRankOut 需要的数据
 * @param orderIsDesc  默认 true desc(降序,从大到小) 
 * @param data [{key, value, details}]
 * @param max 最大值
 * @param unit 单位
 * @returns  {unit, max, dataInfo:[{key, value, details, unit}, {}, {}, {}] }
 */
export function rankPackage(data, orderIsDesc = true, unit?, max?) {
    let dataInfo = [];
    let valueIsString = false;
    let dataUnitDistinctMap = {};
    data.forEach( info => {
        let key = info.key;
        let value = info.value;
        let details = info.details || "";
        let onceUnit = "";
        checkingError({key}, errorEnum.数据key是否为空);
        if ((value == undefined || value == null) || `${value}`.search(/^(-)?\d+(\.\d+)?/) == -1 ) {
            valueIsString = true;
        } else  {
            let {dataNum, dataUnit} = separateDataAndUint(value);
            if (dataUnit) {
                dataUnitDistinctMap[dataUnit] = 1;
                onceUnit = dataUnit;
            }
            value = dataNum;
        }
        dataInfo.push({key, value, details, unit:onceUnit});
    });

    let dataUnitList = Object.keys(dataUnitDistinctMap);
    if (dataUnitList.length > 1) throw new BizError(`在 rankPackage 中 数据中的value解析出来不统一的单位:${JSON.stringify(dataUnitList)}`);
    if (dataUnitList.length && unit && unit != dataUnitList.length) throw new BizError(`在 rankPackage 中 入参单位${unit} 与 数据中解析出来的单位 ${dataUnitList[0]} 不一致`);
    let dataUnit = dataUnitList[0] || unit;
    //统一单位
    dataInfo.forEach(info => {info.unit = dataUnit});
    if (!valueIsString) {
        dataInfo.sort( (a, b) => { 
            return orderIsDesc ? b.value - a.value : a.value - b.value;
        });
    }
    
    return {unit:dataUnit, max:max || 0, dataInfo};
}
 

/**
 * radarChartPackage 将会返回 getRadarChartOut 需要的数据
 * @param data [{key, value, max}]
 * @returns [{key, value, max, unit}]
 */
export function radarChartPackage(data) {
    let dataList = [];
    data.forEach(info => {
        let key = info.key;
        let value = info.value;
        let max = info.max;
        checkingError({key}, errorEnum.数据key是否为空);
        checkingError({name:key, value}, errorEnum.数据value是否为数值);

        let {dataNum, dataUnit} = separateDataAndUint(value);

        dataList.push({key, value:dataNum, unit:dataUnit, max});
    });
    return data;
}

/**
 * mapPackage  返回 getMapOut 所需要的数据
 * @param data [{key:数据名称, x:x坐标, y:坐标, longitude:经度, latitude:纬度, value:值, details:补充}]
 * @returns [{name:数据名称, x:x坐标, y:坐标, coordinate:[经度, 纬度], unit:单位,  value:值, details:"补充"}]
 */
export function mapPackage(data, isCoordinate=true, isXY=false) {
    let dataList = [];
    data.forEach((info, index) => {
        checkingError({key:info.key}, errorEnum.数据key是否为空);
        let longitude = info.longitude;
        let latitude = info.latitude;
        let x = info.x;
        let y = info.y;
        let addInfo:any = {key:info.key, details:info.details || ""};
        checkingError({x, y, longitude, latitude, index}, errorEnum.地图坐标判空);
        if (isCoordinate) {
            longitude = isUndefinedOrNull(longitude) ? 0 : longitude;
            latitude = isUndefinedOrNull(latitude) ? 0 : latitude;
            let coordinate = [longitude, latitude];
            addInfo.coordinate = coordinate;
        }
        if (isXY) {
            x = isUndefinedOrNull(x) ? 0 : x;
            y = isUndefinedOrNull(y) ? 0 : y;
            addInfo.x = x;
            addInfo.y = y;
        }

        let value;
        let unit = "";
        if (info.value && `${info.value}`.search(/^(-)?\d+(\.\d+)?/) > -1) {
            let {dataNum, dataUnit} = separateDataAndUint(info.value);
            value = dataNum;
            unit = dataUnit;
            
        } else if (info.value && `${info.value}`.search(/^(-)?\d+(\.\d+)?/) == -1) {
            value = info.value;
        } else value = "";

        addInfo.value = value;
        addInfo.unit = unit;
        dataList.push(addInfo);
        
    });
    return dataList;
}

/**
 * scatterFigurePackage  返回 getScatterFigureOutData 需要的格式
 * @param data [{x, y, name}, {x, y, name}, {x, y, name}, {x, y, name}]
 * @returns [{x, y, name}, {x, y, name}, {x, y, name}, {x, y, name}]
 */
export function scatterFigurePackage(data) {
    let dataList = [];
    data.forEach((info, index) => {
        let x = info.x;
        let y = info.y;
        checkingError({x, y, index}, errorEnum.散点图判空);
        dataList.push({x, y, name:info.name || ""});
    });
    return dataList;
}



enum errorEnum {
    必要参数 = 1,
    数据key是否为空,
    数据value是否为数值,
    类型为string,
    barChart中x轴的key重复出现,
    值为undefined或null,
    地图坐标判空,
    散点图判空
};
function checkingError(param, errorEnumType) {
    let str = ``;
    let isError = false;
    switch(errorEnumType) {
        case errorEnum.类型为string:
            if ( typeof param.str != "string") {
                isError = true;
                str += `下标为${param.index}的数据 不为string,当前为${param.str}`;
            }
        break;
        case errorEnum.必要参数:
            let paramNullErrorStr = '必要参数: ';
            for (let key in param) {
                if (!param[key]) {
                    isError = true;
                    paramNullErrorStr += `${key}为空 `;
                }
            }
            str += paramNullErrorStr;
        break;
        case errorEnum.数据key是否为空 :
            if (!param.key) {
                isError = true;
                str += `${param.name}中有key缺失数据`;
            }
        break;
        case errorEnum.数据value是否为数值: 
            if (`${param.value}`.search(/^(-)?\d+(\.\d+)?/) == -1) {
                isError = true;
                str += `${param.name}中 key为${param.key} 的数据为字符串`;
            }
        break;
        case errorEnum.barChart中x轴的key重复出现: 
            if (param.distinctMap[param.key]) {
                isError = true;
                str += `${param.name}中 key为${param.key} 在数据中重复出现`;
            }
        break;
        case errorEnum.值为undefined或null:
            if ( isUndefinedOrNull(param.value) ) {
                isError = true;
                str += `${param.key}的值 为 undefined 或 null`;
            }
        break;
        case errorEnum.地图坐标判空:
            if (isUndefinedOrNull(param.x) && isUndefinedOrNull(param.y) && isUndefinedOrNull(param.longitude) && isUndefinedOrNull(param.latitude)) {
                isError = true;
                str += `第${param.index+1}个数据中坐标异常 所有表示坐标的属性都为空`;
            }
            if ( (isUndefinedOrNull(param.x) || isUndefinedOrNull(param.y)) && isUndefinedOrNull(param.longitude) || isUndefinedOrNull(param.latitude) ) {
                isError = true;
                str += `第${param.index+1}个数据中坐标异常 xy坐标缺失的同时经纬度也缺失`;
            }
        break;
        case errorEnum.散点图判空:
            if (isUndefinedOrNull(param.x) || isUndefinedOrNull(param.y)) {
                isError = true;
                str += `第${param.index+1}个数据中坐标异常 x为${param.x} y为${param.y}`;
            }
        break;
        
    }

    if (isError) {
        throw new BizError(str);
    }
}

function isUndefinedOrNull(paramater) {
    return paramater == undefined || paramater == null;
}