// 兵种表
import { readFileAndParse, parseNumberList, parseGoodStr, decodeArrayListStr} from '../util'
import { FILENAME, } from '../../consts'
import { RewardInter } from '../interface';
const _ = require('lodash');

export interface DicJob {
    // 兵种id
    readonly jobid: number;
    // 兵种名
    readonly name: string;
    // 该兵种在大兵种中的阶段
    readonly grade: number;
    // 解锁等级
    readonly unlockLevel: number;
    // 兵种类别
    readonly job_class: number;
    // 职业类别
    readonly type: number;
    // // 特性
    // readonly seid: Array<number>;
    // 训练消耗
    readonly trainingConsume: Array<RewardInter>;
    // 升阶消耗
    readonly upGradeConsume: Array<RewardInter>;
    // 每阶升级属性 stage => {}
    readonly ceAttr: Map<number, {id: number, attr: number}[]>;
    // 次级属性基础 attr => value attr1
    readonly baseSubAttr: {id: number, val: number}[];
    // 一共有多少阶升级
    readonly maxStage: number;
    // 到这一阶有多少天赋点
    readonly talentPoint: number;
}

type KeysEnum<T> = { [P in keyof Required<T>]: true };
const DicJobKeys: KeysEnum<DicJob> = {jobid: true, name: true, grade: true, unlockLevel: true, job_class: true, type: true, trainingConsume: true, upGradeConsume: true, ceAttr: true, maxStage: true, talentPoint: true, baseSubAttr: true};

export const dicJob = new Map<number, DicJob>();
export const jobClassMaxGrades = new Map<number, {grade:number, jobid:number}>();
export const jobClassAndgrades = new Map<string, {jobid:number, unlockLevel:number}>();
export const talentPointOfJob = new Map<number, number>();

export function loadJob() {
    dicJob.clear();
    jobClassMaxGrades.clear();
    jobClassAndgrades.clear();
    talentPointOfJob.clear();
    
    let arr = readFileAndParse(FILENAME.DIC_JOB);
    // let jobByJobClass = new Map<number, number[]>(); // jobClass => jobid[]
    let lastJob: DicJob;

    arr.forEach(o => {
        if(o.isPlayer) {
            o.seid = parseNumberList(o.seid);
            o.trainingConsume = parseGoodStr(o.trainingConsume);
            o.maxStage = 6;
            o.upGradeConsume = parseGoodStr(o.upGradeConsume);
            o.ceAttr = parseCeAttr(o.maxStage, o.attr, lastJob, o.job_class);
            o.baseSubAttr = parseAttribute(o.baseAttr||'');
            dicJob.set(o.jobid, _.pick(o, Object.keys(DicJobKeys)));
            let jobClass = jobClassMaxGrades.get(o.job_class);
            if (!jobClass || jobClass.grade < o.grade) {
                jobClassMaxGrades.set(o.job_class, {grade: o.grade,jobid: o.jobid});
            }
            jobClassAndgrades.set(o.job_class+'_'+o.grade,{unlockLevel:o.unlockLevel, jobid:o.jobid});   
            // if(!jobByJobClass.has(o.job_class)) {
            //     jobByJobClass.set(o.job_class, []);
            // } 
            // jobByJobClass.get(o.job_class).push(o.jobid);
            talentPointOfJob.set(o.jobid, o.talentPoint);
            lastJob = o;
        }
    });
    // for(let [_, { job_class, talentPoint }] of dicJob) {
    //     let jobs = jobByJobClass.get(job_class)||[];
    //     for(let jobid of jobs) {
    //         if(!talentPointOfJob.has(jobid)) {
    //             talentPointOfJob.set(jobid, talentPoint);
    //         } else {
    //             talentPointOfJob.set(jobid, talentPointOfJob.get(jobid) + talentPoint);
    //         }
    //     }
    // }
    
    // jobByJobClass = undefined;
    arr = undefined;
}

function parseCeAttr(maxStage: number, str: string, lastJob: DicJob, job_class: number) {
    let result = new Map<number, { id: number, attr: number }[]>();
    for (let i = 0; i <= maxStage; i++) {
        if(lastJob && lastJob.job_class == job_class && lastJob.ceAttr && lastJob.ceAttr.has(maxStage)) {
            let attrs: { id: number, attr: number }[] = [];
            for(let { id, attr} of lastJob.ceAttr.get(maxStage)||[]) {
                attrs.push({ id, attr });
            }
            result.set(i, attrs)
        } else {
            result.set(i, []);
        }
    }
    if (!str) return result;
    let decodeArr = decodeArrayListStr(str);
    for (let i = 1; i <= maxStage; i++) {
        let [id, attr] = decodeArr[i - 1]||[i.toString(), "0"];
        let _id = parseInt(id);
        let _attr = parseFloat(attr);

        if (isNaN(parseInt(id)) || isNaN(parseInt(attr))) {
            throw new Error('data table format wrong');
        }
        for(let j = i; j <= maxStage; j++) {
            let arr = result.get(j)||[];
            let index = arr.findIndex(cur => cur.id == _id);
            if(index == -1) {
                arr.push({ id: _id, attr: _attr });
            } else {
                arr[index].attr = _attr;
            }
            
            result.set(j, arr);
        }
    }
    return result
}

function parseAttribute(str: string) {
    let result = new Array<{ id: number, val: number }>();
    if (!str) return result;
    let decodeArr = decodeArrayListStr(str);
    for (let [id, val] of decodeArr) {
        if (isNaN(parseInt(id)) || isNaN(parseInt(val))) {
            throw new Error('data table format wrong');
        }
        result.push({ id: parseInt(id), val: parseInt(val) });
    }
    return result
}
