import { pick } from 'underscore';
import { ActivityModelType } from '../../db/Activity';
import { ActivityTurntableModelType, TurntableRecord } from '../../db/ActivityTurntableRec';
import { RewardInter } from '../../pubUtils/interface';
import { getRandEelmWithWeight, parseGoodStr } from '../../pubUtils/util';
import { ActivityBase } from './activityField';

/************** 在数据库中的格式 ***********/

interface TurntablePoolInDb {
    id: number;         // 奖池id
    gid: number;        // 物品id
    count: number;      // 道具数量
    weight: number;     // 权重
}

interface TurntableFloorInDb { // 保底，每sum次必出count个头奖，头奖：权重最低的一项
    sum: number;
    count: number;
}

interface TurntableBoxInDb {
    count: number;       // 次数
    rewards: string;      // 奖励 type&id&count
}

interface TurntableInDb {
    cost: string;        // 抽1次的消耗，id&count
    freeCount: number;   // 免费次数
    pool: TurntablePoolInDb[]; // 奖池
    floor: TurntableFloorInDb; // 保底
    box: TurntableBoxInDb[];
}

/************** 给客户端返回的数据 ***********/
// 转盘数据
export class LuckyTurntablePool {
    id: number;      // 奖池项唯一id
    gid: number;     // 物品id
    count: number;   // 物品数量
    weight: number;  // 权重-最好填写整数，会自动做加和，如weight为1,2，则他们的概率为1/3和2/3
    
    constructor(data: TurntablePoolInDb) {
        this.id = data.id;
        this.gid = data.gid;
        this.count = data.count;
        this.weight = data.weight;
    }

    public getShowResult() {
        return pick(this, ['id', 'gid', 'count']);
    }
} 

export class LuckyTurntableBox {
    count: number;       // 次数
    rewards: string;      // 奖励

    isReceived: boolean = false; // 是否已领取

    constructor(data: TurntableBoxInDb) {
        this.count = data.count;
        this.rewards = data.rewards;
    }
    
    public setReceived(box: number[] = []) {
        if(box.indexOf(this.count) != -1) {
            this.isReceived = true;
        }
    }
}

// 新云转盘活动数据
export class LuckyTurntableData extends ActivityBase {
    cost: string;          // 抽1次的消耗
    freeCount: number;     // 免费次数
    pool: LuckyTurntablePool[] = [];
    greateReward: LuckyTurntablePool; // 头奖，weight最小的那一个
    box: LuckyTurntableBox[] = [];
    floor: {               // 保底
        sum: number;
        count: number;
    };

    todayCount: number = 0;    // 今天抽了几次
    count: number = 0;         // 一共抽了几次
    records: TurntableRecord[] = [];     // 奖励记录
    greatRewardCount: number = 0;   // 中头奖次数
    
    public getCost(count: number) {
        if(this.todayCount < this.freeCount) {
            count -= this.freeCount - this.todayCount;
        }
        let cost = parseGoodStr(this.cost);
        return cost.map(cur => ({...cur, count: cur.count * count}));
    }

    public pull(roleName: string, count: number) {
        let records: (string|number)[][] = [];
        let result: number[] = [];
        let goodResult: RewardInter[] = [];
        for(let i = 0; i < count; i++) {
            let pool = this.pool;
            let numNow = this.count % this.floor.sum;
            let getNumNow = this.greatRewardCount % this.floor.count;
            if(getNumNow >= this.floor.count) { // 不再抽到
                pool = this.pool.filter(cur => cur.id != this.greateReward.id);
                if(pool.length <= 0) pool = this.pool;
            } else if (this.floor.sum - numNow - getNumNow <= this.floor.count) { // 到最后几个了，直接给保底
                pool = [this.greateReward];
            }
            let { dic: randResult } = getRandEelmWithWeight(this.pool);
            if(randResult) {
                this.count++;
                this.todayCount++;
                let record = { roleName, gid: randResult.gid, count: randResult.count };
                records.push([record.roleName, record.gid, record.count]);
                this.records.push(record);
                result.push(randResult.id);
                goodResult.push({ id: randResult.gid, count: randResult.count });
                if(randResult.id == this.greateReward.id) {
                    this.greatRewardCount++
                }
            }
        }
        return { result, records, goodResult };
    }

    // 宝箱是否可以领取
    public canReceive(boxCount: number) {
        if(this.count < boxCount) return false;
        let box = this.box.find(cur => cur.count == boxCount);
        if(!box) return false
        if(box.isReceived) return false;
        return true;
    }

    public findBox(boxCount: number) {
        let box = this.box.find(cur => cur.count == boxCount);
        return box;
    }

    public setPlayerRecords(playerData: ActivityTurntableModelType) {
        if(!playerData) return null
        let { todayCount, count, records, box, greatRewardCount } = playerData;
        this.todayCount = todayCount;
        this.count = count;
        this.records = records;
        for(let boxData of this.box) {
            boxData.setReceived(box);
        }
        this.greatRewardCount = greatRewardCount;
    }

    public initData(data: string) {
        let dataObj: TurntableInDb = JSON.parse(data);
        this.cost = dataObj.cost;
        this.freeCount = dataObj.freeCount;
        for(let pool of dataObj.pool) {
            let poolObj = new LuckyTurntablePool(pool);
            this.pool.push(poolObj);
            if(!this.greateReward || this.greateReward.weight > poolObj.weight) {
                this.greateReward = poolObj;
            }
        }
        for(let box of dataObj.box) {
            this.box.push(new LuckyTurntableBox(box));
        }
        this.floor = dataObj.floor;
    }

    public getShowResult() {
        return {
            ...this.getBaseKeys(),
            cost: this.cost,
            freeCount: this.freeCount,
            todayCount: this.todayCount,
            count: this.count,
            box: this.box,
            pool: this.pool.map(pool => pool.getShowResult()),
            records: this.records.map(record => [record.roleName, record.gid, record.count])
        }
    }

    constructor(activityData: ActivityModelType, createTime: number, serverTime: number) {
        super(activityData, createTime, serverTime)
        this.initData(activityData.data)
    }
}