import { Application, BackendSession, HandlerService, } from "pinus";
import { STATUS, CONSUME_TYPE, DEBUG_MAGIC_WORD } from "../../../consts";
import { RewardInter } from "../../../pubUtils/interface";

import { resResult } from "../../../pubUtils/util";
import { addItems, handleCost } from "../../../services/rewardService";
import { RoleModel } from "../../../db/Role";
import { gameData } from "../../../pubUtils/data";
import { ITID } from "../../../consts/constModules/itemConst";
import { useGiftPackage } from "../../../services/activity/giftPackageService";
import { getAp, setAp, setApBuyTimes } from "../../../services/actionPointService";
import { ActionPointModel } from "../../../db/ActionPoint";
import { GiftCodeDetailModel } from "../../../db/GiftCodeDetail";
import { GiftCodeType, GiftCodeModel } from "../../../db/GiftCode";
import UserGiftCode, { UserGiftCodeModel } from "../../../db/UserGiftCode";

export default function (app: Application) {
    new HandlerService(app, {});
    return new ItemHandler(app);
}

export class ItemHandler {

    constructor(private app: Application) {
    }


    // 道具的使用
    public async useItem(msg: { id: number, selected: Array<number>, count: number }, session: BackendSession) {
        let { id, selected, count } = msg;
        const roleId = session.get('roleId');
        const serverId = session.get('serverId');
        const sid = session.get('sid');
        const roleName = session.get('roleName');
        

        if (count > 0) {
            let consumeResult = await handleCost(roleId, sid, [{ id: id, count: count }]);
            if (!consumeResult) return resResult(STATUS.ACTIVITY_RES_NOT_ENOUGH);

            let dicGoods = gameData.goods.get(id);
            if (!dicGoods) {
                return resResult(STATUS.ACTIVITY_DATA_ERROR);
            }
            let dicItid = ITID.get(dicGoods.itid);
            if (!dicItid) return resResult(STATUS.DIC_DATA_NOT_FOUND);
            if (dicItid.type != CONSUME_TYPE.GIFT_PACKAGE) {
                return resResult(STATUS.NOT_CONSUME_GOODS);
            }
            let giftID = dicGoods.gift;
            if (!giftID) {
                return resResult(STATUS.NOT_GIFTPACKAGE);
            }
            let result = await useGiftPackage(roleId, roleName, sid, serverId, giftID, selected, count)

            return resResult(STATUS.SUCCESS, result);
        }

        return resResult(STATUS.WRONG_PARMS);

    }

    // 使用体力道具
    public async useApItem(msg: { id: number, count: number }, session: BackendSession) {
        let { id, count } = msg;
        const roleId = session.get('roleId');
        const sid = session.get('sid');
        

        if (count > 0) {
            let dicGoods = gameData.goods.get(id);
            if (!dicGoods) {
                return resResult(STATUS.DIC_DATA_NOT_FOUND);
            }
            let dicItid = ITID.get(dicGoods.itid);
            if (!dicItid) return resResult(STATUS.DIC_DATA_NOT_FOUND);
            if (dicItid.type != CONSUME_TYPE.AP) {
                return resResult(STATUS.ROLE_METERIAL_ERROR);
            }

            let role = await RoleModel.findByRoleId(roleId, 'lv');
            let { isOver } = await getAp(roleId, role.lv);
            if (isOver) return resResult(STATUS.AP_IS_FULL);

            let consumeResult = await handleCost(roleId, sid, [{ id: id, count: count }]);
            if (!consumeResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH);

            let apJson = await setAp(roleId, role.lv, dicGoods.value * count, sid);

            return resResult(STATUS.SUCCESS, {
                apJson
            });
        }

        return resResult(STATUS.WRONG_PARMS);

    }

    // 购买体力道具
    public async buyApItem(msg: { id: number, count: number }, session: BackendSession) {
        let { id, count } = msg;
        const roleId: string = session.get('roleId');
        const roleName: string = session.get('roleName');
        const sid: string = session.get('sid');

        if (count <= 0) return resResult(STATUS.WRONG_PARMS);

        let dicGoods = gameData.goods.get(id);
        if (!dicGoods) {
            return resResult(STATUS.DIC_DATA_NOT_FOUND);
        }
        let dicItid = ITID.get(dicGoods.itid);
        if (!dicItid) return resResult(STATUS.DIC_DATA_NOT_FOUND);
        if (dicItid.type != CONSUME_TYPE.AP) {
            return resResult(STATUS.ROLE_METERIAL_ERROR);
        }

        let role = await RoleModel.findByRoleId(roleId, 'lv');
        let { buyTimes = 0 } = await getAp(roleId, role.lv);
        if (buyTimes + count > gameData.apMaxBuyTimes.max) return resResult(STATUS.AP_BUY_TIMES_LACK);

        let cost: RewardInter[] = [];
        for (let i = 0; i < count; i++) {
            let curCost = gameData.apBuy.get(++buyTimes);
            if (curCost) cost = cost.concat(curCost);
        }

        let consumeResult = await handleCost(roleId, sid, cost);
        if (!consumeResult) return resResult(STATUS.BATTLE_CONSUMES_NOT_ENOUGH);

        let goods = await addItems(roleId, roleName, sid, [{ id, count }]);
        let apJson = await setApBuyTimes(roleId, role.lv, sid, count);

        return resResult(STATUS.SUCCESS, {
            goods, apJson
        });
    }

    // 兑换礼包码
    public async useGiftCode(msg: { code: string }, session: BackendSession) {
        const roleId: string = session.get('roleId');
        const roleName: string = session.get('roleName');
        const sid: string = session.get('sid');
        const { code } = msg;

        let giftCodeDetail = await GiftCodeDetailModel.findByCode(code);
        if(!giftCodeDetail) {
            return resResult(STATUS.GIFT_CODE_NOT_FOUND);
        }
        let giftCode = <GiftCodeType>giftCodeDetail.giftCode;
        if(!giftCode) {
            return resResult(STATUS.GIFT_CODE_NOT_FOUND);
        }

        if (giftCode.isLimit && giftCodeDetail.usedNum >= giftCode.count) {
            return resResult(STATUS.GIFT_CODE_USED_NUM_MAX);
        }
        if (giftCode.beginTime > new Date()) return resResult(STATUS.GIFT_CODE_NOT_START);
        if (giftCode.endTime < new Date()) return resResult(STATUS.GIFT_CODE_HAS_EXPIRED);

        let userGiftCode = await UserGiftCodeModel.findByCode(roleId, code);
        if (userGiftCode) {
            return resResult(STATUS.YOU_HAVE_USED_THIS_CODE);
        }

        await UserGiftCode.createCode(roleId, code, giftCode);
        await GiftCodeDetailModel.increaseUsedNum(code);
        await GiftCodeModel.increaseUsedNum(giftCode.id);

        let goods = await addItems(roleId, roleName, sid, giftCode.goods);
        return resResult(STATUS.SUCCESS, { goods });
    }

    public async debugIncAp(msg: { magicWord: string, ap: number }, session: BackendSession) {
        const { magicWord } = msg;
        if (magicWord !== DEBUG_MAGIC_WORD) {
            return resResult(STATUS.TOKEN_ERR);
        }

        const roleId = session.get('roleId');
        const sid = session.get('sid');
        

        let role = await RoleModel.findByRoleId(roleId, 'lv');
        let apJson = await setAp(roleId, role.lv, msg.ap, sid);
        if (!apJson) return resResult(STATUS.BATTLE_ACTION_POINT_LACK)
        return resResult(STATUS.SUCCESS, { apJson });
    }

    public async debugGetAp(msg: { magicWord: string }, session: BackendSession) {
        const { magicWord } = msg;
        if (magicWord !== DEBUG_MAGIC_WORD) {
            return resResult(STATUS.TOKEN_ERR);
        }
        let roleId = session.get('roleId');

        let role = await RoleModel.findByRoleId(roleId, 'lv');
        let apJson = await getAp(roleId, role.lv);
        return resResult(STATUS.SUCCESS, { apJson });
    }

    public async debugResetBuyTimes(msg: { magicWord: string }, session: BackendSession) {
        const { magicWord } = msg;
        if (magicWord !== DEBUG_MAGIC_WORD) {
            return resResult(STATUS.TOKEN_ERR);
        }
        let roleId = session.get('roleId');
        let role = await RoleModel.findByRoleId(roleId, 'lv');
        await ActionPointModel.resetBuyTimes(roleId);
        let apJson = await getAp(roleId, role.lv);
        return resResult(STATUS.SUCCESS, { apJson });
    }
}