import { STATUS } from './../consts/statusCode';

import { isNumber } from 'underscore';

const csprng = require('csprng');
const fs = require('fs');
const path = require('path');
import { ABI_STAGE, REFRESH_TIME, ROBOT_SYS_TYPE, ITEM_CHANGE_REASON, WAR_TYPE, SHOP_REFRESH_TYPE, GACHA_TYPE, GACHA_FLOOR_TYPE } from '../consts';

import { findIndex } from 'underscore';
import { getZeroPointD, getZeroPointOfTimeD } from './timeUtil';
import { Floor } from '../domain/activityField/gachaField';
import { RewardInter } from './interface';
import { gameData } from './data';
const randomName = require("chinese-random-name");
const moment = require('moment');
const crypto = require('crypto');

export function aesEncrypt(data, key, iv) {
    const cipher = crypto.createCipheriv('aes-192-cbc', key, iv);
    let crypted = cipher.update(data, 'utf8', 'hex');
    crypted += cipher.final('hex');
    return crypted;
}

export function aesDecrypt(data, key, iv) {
    const decipher = crypto.createDecipheriv('aes-192-cbc', key, iv);
    let decrypted = decipher.update(data, 'hex', 'utf8');
    decrypted += decipher.final('utf8');
    return decrypted;
}

export function aesEncryptcfb(data, key, iv) {
    const cipher = crypto.createCipheriv('aes-192-cfb', key, iv);
    let crypted = cipher.update(data, 'utf8', 'hex');
    crypted += cipher.final('hex');
    // console.log('****aesEncryptcfb', data, crypted)
    return crypted;
}

export function aesDecryptcfb(data, key, iv) {
    if (data) {
        const decipher = crypto.createDecipheriv('aes-192-cfb', key, iv);
        let decrypted = decipher.update(data, 'hex', 'utf8');
        decrypted += decipher.final('utf8');
        return decrypted;
    } else {
        return ''
    }
}

export function genCode(len) {
    const chars = '123456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijklmnopqrstuvwxyz';
    const charArr = chars.split('');
    let code = '';
    for (let i = 0; i < len; i++) {
        code += charArr[Math.floor(Math.random() * charArr.length)];
    }
    return code;
}

  /**
   * 生成 len 长度的随机字符串
   * @param len 长度
   * @param radix 基数
   */
export function generateStr(len: number, radix = 36) {
    return `${csprng(len, radix)}`;
}

export function generateNum(len: number) {
    let code = '';
    for (let i = 0; i < len; i++) {
        code += parseInt(`${Math.random() * 10}`);
    }
    return code;
}

/**
 * 将 | 分隔的字符串解析为数组，如：a|b|c 解析为[a, b, c]
 * @param str 要解析的字符串
 */
export function decodeArrayStr(str: string, splitForm = '|') {
    let last = str.substr(str.length - 1, 1);
    if (last == '&') str = str.substr(0, str.length - 1);
    if (str == '') {
        return new Array<string>()
    } else {
        return str.split(splitForm);
    }
}

/**
 * 将 | 和 & 分隔的字符串解析为 Map，，如：a&b&c|c&d&f 解析为 [[a,b,c], [c,d,f]]
 * @param str 要解析的字符串
 */
export function decodeArrayListStr(str: string) {
    return decodeArrayStr(str).map(cur => decodeArrayStr(cur, '&'));
}

/**
 * 将 | 和 & 分隔的字符串解析为 Map，，如：a&b|c&d|e&f 解析为 Map {a=>b, c=>d, e=>f}
 * @param str 要解析的字符串
 */
export function decodeIdCntArrayStr(str: string, multi: number) {
    const strArr = decodeArrayStr(str);
    // console.log('decodeIdCntArrayStr: ', strArr);
    const strMap = new Map<string, number>();
    strArr.forEach(item => {
        const kv = item.split('&');
        strMap.set(kv[0], multi ? Math.ceil(parseInt(kv[1]) * multi) : parseInt(kv[1]));
    });
    return strMap;
}

/**
 * 传入两个时间，返回按照时间差计算，第二个时间比第一个晚几天
 * @param preTime 之前的时间
 * @param proTime 之后的时间
 */
export function deltaDays(preTime: Date, proTime: Date, useNaturalZero = false): number {
    let beginZeroPoint = getZeroPointOfTimeD(preTime, SHOP_REFRESH_TYPE.DAILY, useNaturalZero? 0: REFRESH_TIME);
    let endZeroPoint = getZeroPointOfTimeD(proTime, SHOP_REFRESH_TYPE.DAILY, useNaturalZero? 0: REFRESH_TIME);
    return moment(endZeroPoint).diff(moment(beginZeroPoint), "days");
}

/**
 * 计算按照每 x 天 y 点刷新一次，是否应该刷新
 * @param preTime 基准时间
 * @param curTime 当前时间
 * @param hour 几点刷新
 * @param deltaDay 间隔几天刷新，默认每天刷新(deltaDay = 1)
 */
export function shouldRefresh(preTime: Date, now: Date, hour: number = REFRESH_TIME, deltaDay = 1): boolean {
    if (!preTime) return true;
    let curTime = new Date(now.getTime());
    let refreshTime = getZeroPointD(SHOP_REFRESH_TYPE.DAILY, hour);
    let refeshTime = refreshTime.getTime();
    if (refeshTime - preTime.getTime() > (deltaDay >= 1 ? deltaDay - 1 : 0) * 24 * 60 * 60 * 1000 && curTime.getTime() >= refeshTime) {
        return true;
    }
    return false;
}

/**
 * 计算按照每 x 天 y 点刷新一次，是否应该刷新
 * @param preTime 基准时间
 * @param curTime 当前时间
 * @param day 周几刷新
 * @param hour 几点刷新
 * @param deltaDay 间隔几天刷新，默认每天刷新(deltaDay = 1)
 */
export function shouldRefreshWeek(preTime: Date, now: Date, hour: number = REFRESH_TIME, deltaWeek = 1): boolean {
    if (!preTime) return true;
    let curTime = new Date(now.getTime());
    let refreshTime = getZeroPointD(SHOP_REFRESH_TYPE.WEEKLY, hour);
    let refeshTime = refreshTime.getTime();

    if (refeshTime - preTime.getTime() > (deltaWeek >= 1 ? deltaWeek - 1 : 0) * 7 * 24 * 60 * 60 * 1000 && curTime.getTime() >= refeshTime) {
        return true;
    }
    return false;
}

/**
 * 从一个数组中随机返回不重复的 cnt 个元素数组
 * @param source 原数组
 * @param cnt 返回随机元素个数
 */
export function getRandEelm<T>(source: Array<T> = [], cnt = 1): Array<T> {
    if (cnt == 0) return [];
    if (cnt >= source.length) return sortArrRandom(source);
    let idxs = new Set();

    while (1) {
        let rand = Math.floor(Math.random() * source.length);
        idxs.add(rand);
        if (idxs.size >= cnt) {
            break;
        }
    }

    return source.filter((_item, idx) => idxs.has(idx));
}

/**
 * 从一个数组中随机返回1元素
 * @param source 
 */
export function getRandSingleEelm<T>(source: Array<T>): T {
    let len = source.length;
    return source[Math.floor(Math.random() * len)]
}

/**
 * 随机数组中一个index
 * @param len 
 */
export function getRandSingleIndex(len: number) {
    return Math.floor(Math.random() * len);
}

/**
 * 从一个数组根据权重随机一个元素
 * @param randomList 
 */
export function getRandEelmWithWeight<T extends { weight: number }>(randomList: T[]): { dic: T, index: number } {
    let len = randomList.reduce((pre, cur) => {
        return pre + (cur.weight||0);
    }, 0);
    let index = Math.floor(Math.random() * len);
    let result = { dic: null, index: -1 };
    for (let i = 0; i < randomList.length; i++) {
        let { weight = 0 } = randomList[i];
        if (index < weight) {
            result.dic = randomList[i];
            result.index = i;
            break;
        }
        index -= weight;
    }
    return result
}

/**
 * 不改变原数组长度，将内部元素打乱
 * @param source 
 */
export function sortArrRandom<T>(source: T[] = []): T[] {
    let newArr: T[] = [...source];
    return newArr.sort(() => { return Math.random() - 0.5; });
}

/**
 * 在给定数值的浮动范围中随机一个值
 * @param base 基础数值
 * @param ratio 随机范围：base 值上下浮动 ratio(小于 1 的整数)
 * @param decimal 返回值保留的小数位数
 */
export function getRandValue(base: number, ratio: number, decimal = 2): number {
    return parseFloat((base * (1 - ratio + Math.random() * ratio * 2)).toFixed(decimal));
}


/**
 * 在给定最大最小值中随机一个值
 * @param min 最小
 * @param max 最大
 * @param decimal 返回值保留的小数位数
 */
export function getRandValueByMinMax(min: number, max: number, decimal = 2): number {
    let pow = Math.pow(10, decimal);
    return Math.floor((min + (max - min) * Math.random()) * pow)/pow;

}

export function resResult<T>(status: { code: number, simStr: string }, data: T = <T>{}, customMsg = ''): { code: number, msg: string, data: T } {
    const { code, simStr } = status;
    if (code !== STATUS.SUCCESS.code) {
        console.log(`normal err, code: ${code}, des: ${customMsg || simStr}`);
    }
    return { code, msg: customMsg || simStr, data };
}

export function getResStr(status: { code: number, simStr: string }) {
    return status.simStr;
}

// 消除 js 浮点计算bug

export const cal = {
    add: function (a: number, b: number) {
        var c: number, d: number, e: number;
        try {
            c = a.toString().split(".")[1].length;
        } catch (f) {
            c = 0;
        }
        try {
            d = b.toString().split(".")[1].length;
        } catch (f) {
            d = 0;
        }
        e = Math.pow(10, Math.max(c, d));
        return (this.mul(a, e) + this.mul(b, e)) / e;
    },
    sub: function sub(a: number, b: number) {
        var c: number, d: number, e: number;
        try {
            c = a.toString().split(".")[1].length;
        } catch (f) {
            c = 0;
        }
        try {
            d = b.toString().split(".")[1].length;
        } catch (f) {
            d = 0;
        }
        e = Math.pow(10, Math.max(c, d));
        return (this.mul(a, e) - this.mul(b, e)) / e;
    },
    mul: function mul(a: number, b: number) {
        var c = 0,
            d = a.toString(),
            e = b.toString();
        try {
            c += d.split(".")[1].length;
        } catch (f) { }
        try {
            c += e.split(".")[1].length;
        } catch (f) { }
        return Number(d.replace(".", "")) * Number(e.replace(".", "")) / Math.pow(10, c);
    },
    div: function div(a: number, b: number) {
        var c: number, d: number, e = 0,
            f = 0;
        try {
            e = a.toString().split(".")[1].length;
        } catch (g) { }
        try {
            f = b.toString().split(".")[1].length;
        } catch (g) { }
        c = Number(a.toString().replace(".", ""));
        d = Number(b.toString().replace(".", ""));
        return this.mul(c / d, Math.pow(10, f - e));
    }
};

export function getDecimalCnt(num: number) {
    let str = num.toString();
    return str.split('.')[1]? str.split('.')[1].length: 0;
}

//计算公式
// export function calculateNum(ratio: { A: number, B: number }, params: { num: number }, defaultVal = 0) {
//     // result = a * num + b
//     try {
//         let { A, B } = ratio;
//         let { num } = params;
//         let result = A * num + B;
//         if (isNaN(result)) {
//             console.error('calculate wrong: ', A, B, num)
//             return defaultVal;
//         } else {
//             return result;
//         }
//     } catch (e) {
//         console.error(e);
//         return defaultVal;
//     }
// }

export function ratioReward(reward: {id: number, count: number}[], ratio: number): {id: number, count: number}[] {
    return reward.map(cur => {
        return {id: cur.id, count: cur.count * ratio}
    });
}

export function getItems(str: string) {
    let arr = new Array<{ id: number, count: number }>();
    let strArr = str.split('|');
    for (let item of strArr) {
        var itemArr = item.split('&');
        arr.push({
            id: parseInt(itemArr[0]),
            count: parseInt(itemArr[1])
        });
    }
    return arr;
}

export function deepCopy(obj) {
    if (typeof obj !== 'object' || obj === null) {
        return obj;
    }
    var target;
    if (obj instanceof Array) {
        target = [];
        obj.forEach(element => {
            target.push(deepCopy(element));
        });
    } else {
        target = {};
        for (const key in obj) {
            if (obj.hasOwnProperty(key)) {
                const element = obj[key];
                if (!!element || element == 0) {
                    target[key] = deepCopy(element);
                }
            }
        }
    }
    return target;
};

export function readFile(addr: string) {
    return fs.readFileSync(path.resolve(__dirname, `${addr}`)).toString('utf8').replace(/^\uFEFF/, '');
}

export function writeFile(addr: string, data: string) {
    return fs.writeFileSync(addr, data);
}

export function readFileAndParseJson(path: string) {
    try {
        let readResult = readFile(path);
        return JSON.parse(readResult);
    } catch(e) {
        throw new Error(`connectors.json 格式错误：${(<Error>e).message}`);
    }
}

export function readJsonFile(fileName: string) {
    const folder = 'jsons';
    return fs.readFileSync(path.resolve(__dirname, `../resource/${folder}/${fileName}.json`)).toString('utf8').replace(/^\uFEFF/, '');
}

export function readWarJsonFileList() {
    const folder = 'warJsons';
    return fs.readdirSync(__dirname + `/../resource/${folder}`)
        .filter(cur => { return cur.indexOf('.') != 0 })
        .map(file => {
            return {
                name: file,
                str: fs.readFileSync(path.resolve(__dirname, `../resource/${folder}/${file}`)).toString('utf8')
            }
        });
}

export function readWordTxt(fileName: string) {
    try {
        let file =  fs.readFileSync(path.resolve(__dirname, `../resource/${fileName}.txt`)).toString('utf8').replace(/^\uFEFF/, '');
        return file;
    } catch(e) {
        console.log(e)
        return null
    }
}

export function writeWordTxt(fileName: string, words: string) {
    try {
        let file =  fs.writeFileSync(path.resolve(__dirname, `../resource/${fileName}.txt`), words);
        return file;
    } catch(e) {
        return null
    }
}

export function readTsFile(fileName: string) {
    try {
        let file =  fs.readFileSync(path.resolve(__dirname, `../pubUtils/${fileName}.js`)).toString('utf8').replace(/^\uFEFF/, '');
        return file;
    } catch(e) {
        return null
    }
}

export function readFileAndParse(fileName: string) {
    try {
        let readResult = readJsonFile(fileName);
        return JSON.parse(readResult);
    } catch(e) {
        throw new Error(`${fileName}格式错误：${(<Error>e).message}`);
    }
}

export function readWarJsonFileAndParse() {
    let warJsons = readWarJsonFileList();
    let result = [];
    for(let { name, str } of warJsons) {
        try {
            let json = JSON.parse(str);
            result.push(json);
        } catch(e) {
            throw new Error(`${name}格式错误：${(<Error>e).message}`);
        }
    }
    return result;
}
// 字典表常用解析方法
// 解析物品 {"id": number, "count": number} 格式
export function parseGoodStr(str: string) {
    let result = new Array<{ id: number, count: number }>();
    if (!str) return result;
    let decodeArr = decodeArrayListStr(str);
    for (let [id, count] of decodeArr) {
        if (isNaN(parseInt(id)) || isNaN(parseInt(count))) {
            throw new Error('data table format wrong');
        }
        result.push({ id: parseInt(id), count: parseInt(count) });
    }
    return result
}
// 根据类型解析物品 {"type":number, "id": number, "count": number} 格式
//type 1.英雄，2.物品
export function parseGoodStrWithType(str: string) {
    let result = new Array<{ type: number, id: number, count: number }>();
    if (!str) return result;
    let decodeArr = decodeArrayListStr(str);
    for (let [type, id, count] of decodeArr) {
        if (isNaN(parseInt(type)) || isNaN(parseInt(id)) || isNaN(parseInt(count))) {
            throw new Error('data table format wrong');
        }
        result.push({ type: parseInt(type), id: parseInt(id), count: parseInt(count) });
    }
    return result
}

// 根据类型解析物品 {"type":number, "hid": number, "count": number} 格式
//type 1.英雄，2.物品
export function parseHeroStrWithType(str: string) {
    let result = new Array<{ type: number, hid: number, count: number }>();
    if (!str) return result;
    let decodeArr = decodeArrayListStr(str);
    for (let [type, hid, count] of decodeArr) {
        if (isNaN(parseInt(type)) || isNaN(parseInt(hid)) || isNaN(parseInt(count))) {
            throw new Error('data table format wrong');
        }
        result.push({ type: parseInt(type), hid: parseInt(hid), count: parseInt(count) });
    }
    return result
}

// 根据类型解析物品 {"type":number, "id": number, "count": number} 格式
//type 1.英雄，2.物品, 3.RMB
export function parseResStr(str: string) {
    let result = new Array<{ type: number, id: number, count: number }>();
    if (!str) return result;
    let decodeArr = decodeArrayListStr(str);
    for (let [type, id, count] of decodeArr) {
        if (isNaN(parseInt(type)) || isNaN(parseInt(id)) || isNaN(parseInt(count))) {
            throw new Error('data table format wrong');
        }
        result.push({ type: parseInt(type), id: parseInt(id), count: parseInt(count) });
    }
    return result
}

// 数字列表
export function parseNumberList(str: string) {
    let res = new Array<number>();
    if (!str) return res;
    let arr = decodeArrayStr(`${str}`, '&');
    for (let g of arr) {
        if (g === "") continue;
        res.push(parseFloat(g));
    }
    return res;
}

export function mergeSameGoods(goods: Array<{ id: number, count: number }>) {
    let resGoods = [];
    for (let { id, count } of goods) {
        let index = findIndex(resGoods, { id });
        if (index > -1) {
            resGoods[index].count += count;
        } else {
            resGoods.push({ id, count });
        }
    }
    return resGoods;
}

// 获取全部属性
export function getAllAttrStage() {
    let attrs = new Array<number>(); // 有升级的属性 1-hp 2-atk 3-def 4-mdef 5-agi 6-luk
    for (let stage = ABI_STAGE.START + 1; stage <= ABI_STAGE.END; stage++) {
        attrs.push(stage)
    };
    return attrs;
}

export function getChineseName() {
    return randomName.generate()
}

export function getRobotInfo(sysType?: ROBOT_SYS_TYPE) {
    return {
        robotRoleName: getChineseName(),
        robotRoleId: makeRobotId(genCode(8), sysType),
    }
}

// 根据roleId判断是不是机器人
export function checkRoleIsRobot(roleId: string) {
    return !!roleId.match(/_r/);
}

// 将一般的roleId转为带_r的
export function makeRobotId(roleId: string, sysType?: ROBOT_SYS_TYPE) {
    if(sysType) {
        return `${sysType}|${roleId}_r`;
    } else {
        return `${roleId}_r`;
    }
}
// 获取来源系统
export function getRobotSysType(roleId: string) {
    let type = roleId.split('|')[0];
    if(isNaN(parseInt(type))) {
        return 0
    } else {
        return parseInt(type);
    }

}

// 将一般的roleId去掉_r
export function robotIdComBack(robotRoleId: string) {
    return robotRoleId.replace(/_r/, '')
}

export function splitString(dataString: string, key: string) {
    if (!dataString) {
        return [];
    }
    let array = dataString.split(key).filter(obj => { return obj && obj != '' });
    let numberArray = [];
    for (let num of array) {
        numberArray.push(Number(num));
    }
    return numberArray;
}


export function isTimestamp(time: number, len = 10) {
    if(!isNumber(time)) return false;
    if(time.toString().length != len) return false;
    return true;
}

export function getReasonByWarType(warType: number) {
    switch(warType) {
        case WAR_TYPE.NORMAL:
            return ITEM_CHANGE_REASON.NORMAL_BATTLE_END;
        case WAR_TYPE.VESTIGE:
            return ITEM_CHANGE_REASON.VESTIGE_BATTLE_END;
        case WAR_TYPE.EVENT:
            return ITEM_CHANGE_REASON.EVENT_BATTLE_END;
        case WAR_TYPE.DAILY:
            return ITEM_CHANGE_REASON.DAILY_BATTLE_END;
        case WAR_TYPE.EXPEDITION:
            return ITEM_CHANGE_REASON.EXPEDITION_BATTLE_END;
        case WAR_TYPE.MYSTERY:
            return ITEM_CHANGE_REASON.MYSTERY_BATTLE_END;
        case WAR_TYPE.COM_BATTLE:
            return ITEM_CHANGE_REASON.WARLOARDS_BATTLE_END;
        case WAR_TYPE.TOWER:
            return ITEM_CHANGE_REASON.TOWER_BATTLE_END;
        case WAR_TYPE.PVP:
            return ITEM_CHANGE_REASON.PVP_BATTLE_END;
        // case WAR_TYPE.GUILD_ACTIVITY:
        //     return ITEM_CHANGE_REASON.GUILD_ACTIVITY_BATTLE_END;
        case WAR_TYPE.GUILD_TRAIN:
            return ITEM_CHANGE_REASON.TRAIN_BATTLE_END;
        case WAR_TYPE.MAIN_ELITE:
            return ITEM_CHANGE_REASON.MAIN_ELITE_BATTLE_END;
        // case WAR_TYPE.MYSTERY_ELITE:
        //     return ITEM_CHANGE_REASON.MYSTERY_ELITE_BATTLE_END;
        case WAR_TYPE.BRANCH:
        case WAR_TYPE.BRANCH_ELITE:
            return ITEM_CHANGE_REASON.BRANCH_BATTLE_END;
        case WAR_TYPE.ACT_TREASURE_HUNT:
            return ITEM_CHANGE_REASON.ACT_TREASURE_HUNT_BATTLE_END;
        case WAR_TYPE.ACT_SELF_SHOP:
            return ITEM_CHANGE_REASON.ACT_SELF_SHOP_BATTLE_END;
        case WAR_TYPE.ACT_DAILY_GK:
            return ITEM_CHANGE_REASON.ACT_DAILY_GK_BATTLE_END;
        case WAR_TYPE.ACT_NEW_HERO_GK:
            return ITEM_CHANGE_REASON.ACT_NEW_HERO_GK_BATTLE_END;
        case WAR_TYPE.TRY:
            return ITEM_CHANGE_REASON.TRY_BATTLE_END;
        case WAR_TYPE.BOSS:
            return ITEM_CHANGE_REASON.BOSS_BATTLE_END;
        case WAR_TYPE.LADDER:
            return ITEM_CHANGE_REASON.LADDER_BATTLE_REWARD;
        default: 
            return ITEM_CHANGE_REASON.NORMAL_BATTLE_END;
    }
}

export function getWarTypeName(warType: number) {
    switch(warType) {
      case WAR_TYPE.NORMAL: return '主线';
      case WAR_TYPE.VESTIGE: return '支线';
      case WAR_TYPE.EVENT: return '事件';
      case WAR_TYPE.DAILY: return '每日';
      case WAR_TYPE.EXPEDITION: return '远征';
      case WAR_TYPE.MYSTERY: return '秘境';
      case WAR_TYPE.COM_BATTLE: return '寻宝';
      case WAR_TYPE.TOWER: return '镇念塔';
      case WAR_TYPE.PVP: return '竞技';
      case WAR_TYPE.GUILD_ACTIVITY: return '军团活动';
      case WAR_TYPE.GUILD_TRAIN: return '训练场';
      case WAR_TYPE.MAIN_ELITE: return '主线精英';
      case WAR_TYPE.BRANCH_ELITE: return '梦魇支线';
      case WAR_TYPE.BRANCH: return '支线';
      case WAR_TYPE.ACT_TREASURE_HUNT: return '运营活动-神州探秘';
      case WAR_TYPE.ACT_SELF_SHOP: return '运营活动-糜家商队';
      case WAR_TYPE.ACT_DAILY_GK: return '运营活动-节日活动';
      case WAR_TYPE.ACT_NEW_HERO_GK: return '新武将活动关卡';
      case WAR_TYPE.TRY: return '试用关卡';
      case WAR_TYPE.BOSS: return '演武台';
    }
  }

  /**
   * 一群人分总数固定的东西
   * @param total 总数
   * @param max 每个人能拿到的最大数量
   * @param memberCnt 人数
   */
  export function getRandResultByMember(total: number, max: number, memberCnt: number) {
      let arr: number[] = [];
      for(let i = 1; i <= memberCnt; i++) {
          let randMax = total > max? max: total;
          let randMin = total - (memberCnt - i) * max;
          if(randMin < 0) randMin = 0;
          if(randMin > max) randMin = max;
          let rand = getRandValueByMinMax(randMin, randMax + 1, 0);
          arr.push(rand);
          total -= rand;
      }
      return { arr, remain: total }
  }

//数据格式转换'id&数量|id&数量|' ->> Array<RewardInter> 老资源格式
export function stringToRewardInter(rewardStr: string): Array<RewardInter> {
    let result = new Array<{ id: number, count: number }>();
    if (!rewardStr) return result;
    let decodeArr = decodeArrayListStr(rewardStr);
    for (let [id, count] of decodeArr) {
        if (isNaN(parseInt(id)) || isNaN(parseInt(count))) {
            throw new Error('data table format wrong');
        }
        result.push({ id: parseInt(id), count: parseInt(count) });
    }
    return result
}

export function addToMap<T>(map: Map<T, number>, id: T, value: number) {
    if(!map.has(id)) {
        map.set(id, value);
    } else {
        map.set(id, map.get(id) + value);
    }
}

export function arrToMap<T>(arr: T[], getKey: (obj: T) => number): Map<number, T> {
    let map = new Map();
    for(let obj of arr) {
        let key = getKey(obj);
        map.set(key, obj);
    }
    return map;
}

// /**
//  * 计算最强阵容战力
//  * @param role 
//  * @param hid 
//  * @param ce 
//  * @param heroId 
//  */
//  export async function calculatetopLineup(role: RoleType, hid?: number, ce?: number, heroId?: string) {
//     let topLineup = role?.topLineup || new Array();
//     if(!hid) { // 直接重新排
//         let heroes = await HeroModel.getTopHero(role.roleId, LINEUP_NUM);
//         topLineup = heroes.map(cur => { return { hid: cur.hid, ce: cur.ce, hero: cur._id } });
//     } else {
//         topLineup.sort((a, b) => { return b.ce - a.ce }); // 0-6，最大-最小
//         let index = topLineup.findIndex(cur => cur.hid == hid);
//         if(index != -1 && !heroId) {
//             let heroes = await HeroModel.getTopHero(role.roleId, LINEUP_NUM);
//             topLineup = heroes.map(cur => { return { hid: cur.hid, ce: cur.ce, hero: cur._id } });
//         } else {
//             if (index == -1) { // 不在最强列表
//                 if (topLineup.length < LINEUP_NUM) { // 不满6人
//                     topLineup.push({ hid, ce, hero: heroId });
//                 } else if (topLineup.length == LINEUP_NUM) {
//                     if (ce > topLineup[topLineup.length - 1].ce) { // 跻身最强6人
//                         topLineup.pop();
//                         topLineup.push({ hid, ce, hero: heroId });
//                     }
//                 } else {
//                     topLineup.splice(LINEUP_NUM, topLineup.length - LINEUP_NUM);
//                 }
//             } else { // 原来就是最强6人
//                 if (ce < topLineup[topLineup.length - 1].ce) { // 滑出最强
//                     let heroes = await HeroModel.getTopHero(role.roleId, LINEUP_NUM);
//                     topLineup = heroes.map(cur => { return { hid: cur.hid, ce: cur.ce, hero: cur._id } });
//                 } else {
//                     topLineup[index].ce = ce;
//                 }
//             }
//         }
//     }

//     let topLineupCe = topLineup.reduce((pre, cur) => {
//         return pre + cur.ce
//     }, 0);

//     return { topLineup, topLineupCe };
// }

export function getGachaRemainFloor(gachaId: number, userFloor: Floor[]) {
    let dicGacha = gameData.gacha.get(gachaId);
    if(dicGacha.gachaType != GACHA_TYPE.NORMAL) return 0;

    for(let floorId of dicGacha.floor) {
        let dicGachaFloor = gameData.gachaFloor.get(floorId);
        if(dicGachaFloor && dicGachaFloor.floorType == GACHA_FLOOR_TYPE.MAIN_FLOOR) {
            let myFloor = userFloor.find(cur => cur.id == floorId);

            return dicGachaFloor.param - (myFloor?.count||0);
        }
    }
    return 0
}

export function isDevelopEnv(env: string) {
    const envs = ['development', 'monitor', 'alpha', 'dev'];
    return envs.indexOf(env) != -1;
}

export function getArrayOfNumber(len: number) {
    let arr: number[] = [];
    for(let i = 1; i <= len; i++) arr.push(i);
    return arr;
}