import moment = require('moment');
import { ACTIVITY_TYPE, SERVER_OPEN_TIME, STATUS } from '../../consts';
import { ActivityModel, ActivityModelType } from '../../db/Activity';
import { ActivityTreasureHuntShopModel, ActivityTreasureHuntShopModelType } from '../../db/ActivityTreasureHuntShop';
import { ActivityTreasureHuntTaskModel, ActivityTreasureHuntTaskModelType } from '../../db/ActivityTreasureHuntTask';
import { ActivityTreasureHuntTreasureShopModel, ActivityTreasureHuntTreasureShopModelType } from '../../db/ActivityTreasureHuntTreasureShop';
import { ActivityTreasureHuntFirstPageModel, ActivityTreasureHuntFirstPageModelType } from '../../db/ActivityTreasureHuntFirstPage';
import { ServerlistModel } from '../../db/Serverlist';
import { ServerTempModel, ServerTempModelType } from '../../db/ServerTemp';
import { TreasureHuntData } from '../../domain/activityField/treasureHuntField';
import { deltaDays } from '../../pubUtils/util';
import { addReward, stringToConsumeParam, stringToRewardParam } from './giftPackageService';
import { RewardParam } from '../../domain/activityField/rewardField';
import { RoleModel } from '../../db/Role';

/**
   * 获取活动数据
   *
   * @param {number} serverId 区Id
   * @param {number} type 活动类型 ACTIVITY_TYPE
   * @param {string} roleId 角色Id
   *
   */

export async function treasureHuntActivity(serverId: number, roleId: string) {
    let { huntActivityId, huntBeginTime, huntEndTime, huntRoundIndex, activityData } = await getTreasureHuntData(serverId, roleId);
    if (!activityData) {
        return null;
    }

    let { createTime } = await RoleModel.findByRoleId(roleId);
    let playerData = new TreasureHuntData(activityData, createTime);
    playerData.beginTime = moment(huntBeginTime).valueOf();
    playerData.endTime = moment(huntEndTime).valueOf();
    playerData.todayIndex = deltaDays(moment(huntBeginTime).startOf('d').toDate(), new Date) + 1;;
    playerData.roundIndex = huntRoundIndex;

    let playerTreasureFirstPageecord: ActivityTreasureHuntFirstPageModelType = await ActivityTreasureHuntFirstPageModel.findData(serverId, activityData.activityId, roleId, huntRoundIndex);
    playerData.firstPage.setPlayerFirstPageRecord(playerTreasureFirstPageecord);
    let playerShopRecord: ActivityTreasureHuntShopModelType = await ActivityTreasureHuntShopModel.findTreasureData(activityData.activityId, roleId, huntRoundIndex, playerData.todayIndex);
    playerData.shop.setPlayerShopRecords(playerShopRecord);
    let playerTaskRecord: ActivityTreasureHuntTaskModelType[] = await ActivityTreasureHuntTaskModel.findDataByRoundIndex(serverId, activityData.activityId, roleId, huntRoundIndex);
    playerData.tasks.setPlayerTaskRecords(playerTaskRecord);
    let playerTreasureShopRecord: ActivityTreasureHuntTreasureShopModelType = await ActivityTreasureHuntTreasureShopModel.findData(activityData.activityId, roleId, huntRoundIndex);
    playerData.treasureShop.setPlayerTreasureShopRecords(playerTreasureShopRecord);

    return playerData;
}


/**
   * 获取活动数据
   *
   * @param {number} serverId 区Id
   * @param {number} type 活动类型 ACTIVITY_TYPE
   * @param {string} roleId 角色Id
   *
   */

export async function treasureHuntTaskActivity(serverId: number, roleId: string) {
    let { huntActivityId, huntBeginTime, huntEndTime, huntRoundIndex, activityData } = await getTreasureHuntData(serverId, roleId);
    if (!activityData) {
        return null;
    }

    let { createTime } = await RoleModel.findByRoleId(roleId);
    let playerData = new TreasureHuntData(activityData, createTime);
    playerData.beginTime = moment(huntBeginTime).valueOf();
    playerData.endTime = moment(huntEndTime).valueOf();
    playerData.todayIndex = deltaDays(moment(huntBeginTime).startOf('d').toDate(), new Date) + 1;;
    playerData.roundIndex = huntRoundIndex;

    let playerTaskRecord: ActivityTreasureHuntTaskModelType[] = await ActivityTreasureHuntTaskModel.findDataByRoundIndex(serverId, activityData.activityId, roleId, huntRoundIndex);
    playerData.tasks.setPlayerTaskRecords(playerTaskRecord);
    return playerData;
}

/**
   * 玩家活动数据
   *
   * @param {number} serverId 区Id
   * @param {number} activityId 活动Id
   * @param {string} roleId 角色Id
   *
   */
export async function getPlayerTreasureHuntData(activityId: number, serverId: number, roleId: string, huntRoundIndex: number, huntBeginTime: Date, huntEndTime: Date) {
    let activityData: ActivityModelType = await ActivityModel.findActivity(activityId);

    let { createTime } = await RoleModel.findByRoleId(roleId);
    let playerData = new TreasureHuntData(activityData, createTime);
    playerData.beginTime = moment(huntBeginTime).valueOf();
    playerData.endTime = moment(huntEndTime).valueOf();
    playerData.todayIndex = deltaDays(moment(huntBeginTime).startOf('d').toDate(), new Date) + 1;;
    playerData.roundIndex = huntRoundIndex;

    let playerTreasureFirstPageecord: ActivityTreasureHuntFirstPageModelType = await ActivityTreasureHuntFirstPageModel.findData(serverId, activityId, roleId, huntRoundIndex);
    playerData.firstPage.setPlayerFirstPageRecord(playerTreasureFirstPageecord);
    let playerShopRecord: ActivityTreasureHuntShopModelType = await ActivityTreasureHuntShopModel.findTreasureData(activityId, roleId, huntRoundIndex, playerData.todayIndex);
    playerData.shop.setPlayerShopRecords(playerShopRecord);
    let playerTaskRecord: ActivityTreasureHuntTaskModelType[] = await ActivityTreasureHuntTaskModel.findDataByRoundIndex(serverId, activityId, roleId, huntRoundIndex);
    playerData.tasks.setPlayerTaskRecords(playerTaskRecord);
    let playerTreasureShopRecord: ActivityTreasureHuntTreasureShopModelType = await ActivityTreasureHuntTreasureShopModel.findData(activityId, roleId, huntRoundIndex);
    playerData.treasureShop.setPlayerTreasureShopRecords(playerTreasureShopRecord);

    return playerData;
}

export async function getPlayerTreasureHuntFirstPageData(activityId: number, serverId: number, roleId: string, huntRoundIndex: number, huntBeginTime: Date, huntEndTime: Date) {
    let activityData: ActivityModelType = await ActivityModel.findActivity(activityId);

    let { createTime } = await RoleModel.findByRoleId(roleId);
    let playerData = new TreasureHuntData(activityData, createTime);
    playerData.beginTime = moment(huntBeginTime).valueOf();
    playerData.endTime = moment(huntEndTime).valueOf();
    playerData.todayIndex = deltaDays(moment(huntBeginTime).startOf('d').toDate(), new Date) + 1;;
    playerData.roundIndex = huntRoundIndex;

    let playerTreasureFirstPageecord: ActivityTreasureHuntFirstPageModelType = await ActivityTreasureHuntFirstPageModel.findData(serverId, activityId, roleId, huntRoundIndex);
    playerData.firstPage.setPlayerFirstPageRecord(playerTreasureFirstPageecord);
    return playerData;
}

export async function getPlayerTreasureHuntShopData(activityId: number, serverId: number, roleId: string, huntRoundIndex: number, huntBeginTime: Date, huntEndTime: Date) {
    let activityData: ActivityModelType = await ActivityModel.findActivity(activityId);

    let { createTime } = await RoleModel.findByRoleId(roleId);
    let playerData = new TreasureHuntData(activityData, createTime);
    playerData.beginTime = moment(huntBeginTime).valueOf();
    playerData.endTime = moment(huntEndTime).valueOf();
    playerData.todayIndex = deltaDays(moment(huntBeginTime).startOf('d').toDate(), new Date) + 1;;
    playerData.roundIndex = huntRoundIndex;

    let playerShopRecord: ActivityTreasureHuntShopModelType = await ActivityTreasureHuntShopModel.findTreasureData(activityId, roleId, huntRoundIndex, playerData.todayIndex);
    playerData.shop.setPlayerShopRecords(playerShopRecord);
    return playerData;
}

export async function getPlayerTreasureHuntTaskData(activityId: number, serverId: number, roleId: string, huntRoundIndex: number, huntBeginTime: Date, huntEndTime: Date) {
    let activityData: ActivityModelType = await ActivityModel.findActivity(activityId);

    let { createTime } = await RoleModel.findByRoleId(roleId);
    let playerData = new TreasureHuntData(activityData, createTime);
    playerData.beginTime = moment(huntBeginTime).valueOf();
    playerData.endTime = moment(huntEndTime).valueOf();
    playerData.todayIndex = deltaDays(moment(huntBeginTime).startOf('d').toDate(), new Date) + 1;;
    playerData.roundIndex = huntRoundIndex;

    let playerTaskRecord: ActivityTreasureHuntTaskModelType[] = await ActivityTreasureHuntTaskModel.findDataByRoundIndex(serverId, activityId, roleId, huntRoundIndex);
    playerData.tasks.setPlayerTaskRecords(playerTaskRecord);
    return playerData;
}

export async function getPlayerTreasureHuntChallengeData(activityId: number, serverId: number, roleId: string, huntRoundIndex: number, huntBeginTime: Date, huntEndTime: Date) {
    let activityData: ActivityModelType = await ActivityModel.findActivity(activityId);

    let { createTime } = await RoleModel.findByRoleId(roleId);
    let playerData = new TreasureHuntData(activityData, createTime);
    playerData.beginTime = moment(huntBeginTime).valueOf();
    playerData.endTime = moment(huntEndTime).valueOf();
    playerData.todayIndex = deltaDays(moment(huntBeginTime).startOf('d').toDate(), new Date) + 1;;
    playerData.roundIndex = huntRoundIndex;

    return playerData;
}

export async function getPlayerTreasureHuntTreasureShopData(activityId: number, serverId: number, roleId: string, huntRoundIndex: number, huntBeginTime: Date, huntEndTime: Date) {
    let activityData: ActivityModelType = await ActivityModel.findActivity(activityId);

    let { createTime } = await RoleModel.findByRoleId(roleId);
    let playerData = new TreasureHuntData(activityData, createTime);
    playerData.beginTime = moment(huntBeginTime).valueOf();
    playerData.endTime = moment(huntEndTime).valueOf();
    playerData.todayIndex = deltaDays(moment(huntBeginTime).startOf('d').toDate(), new Date) + 1;;
    playerData.roundIndex = huntRoundIndex;

    let playerTreasureShopRecord: ActivityTreasureHuntTreasureShopModelType = await ActivityTreasureHuntTreasureShopModel.findData(activityId, roleId, huntRoundIndex);
    playerData.treasureShop.setPlayerTreasureShopRecords(playerTreasureShopRecord);
    return playerData;
}

//获取当前活动的周期等数据
export async function getTreasureHuntData(serverId: number, roleId: string) {
    let tempData: ServerTempModelType = await ServerTempModel.findData(serverId);
    let now = moment(new Date()).toDate();
    let activityData: ActivityModelType = null;                    //当前活动数据

    if (!tempData) {//开始新周期
        let { huntActivityId, huntBeginTime, huntEndTime, huntRoundIndex } = await getNewActivityData(serverId, roleId);
        if (huntActivityId === 0) {
            return { huntActivityId, huntBeginTime, huntEndTime, huntRoundIndex, activityData }
        }
        tempData = await ServerTempModel.updateTreasureHuntData(serverId, huntActivityId, huntBeginTime, huntEndTime, huntRoundIndex);
        activityData = await ActivityModel.findActivity(huntActivityId);
        return { huntActivityId, huntBeginTime, huntEndTime, huntRoundIndex, activityData }
    }
    if (now > tempData.huntEndTime) {//活动过期
        let { huntActivityId, huntBeginTime, huntEndTime, huntRoundIndex } = await getNextActivityData(serverId, roleId, tempData.huntActivityId, tempData.huntEndTime, tempData.huntRoundIndex);
        if (huntActivityId === 0) {
            return { huntActivityId, huntBeginTime, huntEndTime, huntRoundIndex, activityData }
        }
        tempData = await ServerTempModel.updateTreasureHuntData(serverId, huntActivityId, huntBeginTime, huntEndTime, huntRoundIndex);
        activityData = await ActivityModel.findActivity(huntActivityId);
        return { huntActivityId, huntBeginTime, huntEndTime, huntRoundIndex, activityData }
    }
    if (!activityData) {
        activityData = await ActivityModel.findActivity(tempData.huntActivityId);
    }
    return {
        huntActivityId: tempData.huntActivityId,
        huntBeginTime: tempData.huntBeginTime,
        huntEndTime: tempData.huntEndTime,
        huntRoundIndex: tempData.huntRoundIndex,
        activityData
    }
}

async function getNewActivityData(serverId: number, roleId: string) {
    let { activityGroupId } = await ServerlistModel.findByServerId(serverId);
    let huntActivityId: number = 0;				// 寻宝骑兵-活动Id
    let huntEndTime: Date = null;					// 寻宝骑兵-结束时间
    let huntRoundIndex: number = 0;				// 寻宝骑兵-周期数
    let activityArray: ActivityModelType[] = await ActivityModel.findActivityByType(activityGroupId, ACTIVITY_TYPE.TREASURE_HUNT, 1)//activityId从小到大排序
    let treasureHuntDataArray: TreasureHuntData[] = [];
    let { createTime } = await RoleModel.findByRoleId(roleId);
    for (let obj of activityArray) {
        treasureHuntDataArray.push(new TreasureHuntData(obj, createTime));
    }
    let isOver = false;
    let huntBeginTime = moment(SERVER_OPEN_TIME).startOf('d').add(1, 'd').toDate();
    let curDate = moment(new Date()).toDate()
    while (!isOver) {
        huntRoundIndex++;
        for (let data of treasureHuntDataArray) {
            let endTime = moment(huntBeginTime).add(data.day, 'd').toDate();
            if (huntBeginTime < curDate && curDate < endTime) {
                huntEndTime = moment(endTime).add(-1, 'm').toDate()
                huntActivityId = data.activityId;
                isOver = true;
            } else {
                huntBeginTime = endTime;
            }
        }
        if (huntRoundIndex >= 365) {//max
            isOver = true;
        }
    }
    return { huntActivityId, huntBeginTime, huntEndTime, huntRoundIndex }
}

async function getNextActivityData(serverId: number, roleId: string, oldHuntActivityId: number, oldHuntEndTime: Date, oldHuntRoundIndex: number) {
    let { activityGroupId } = await ServerlistModel.findByServerId(serverId);
    let huntActivityId: number = 0;				// 寻宝骑兵-活动Id
    let huntEndTime: Date = null;					// 寻宝骑兵-结束时间
    let huntRoundIndex: number = oldHuntRoundIndex;				// 寻宝骑兵-周期数
    let activityArray: ActivityModelType[] = await ActivityModel.findActivityByType(activityGroupId, ACTIVITY_TYPE.TREASURE_HUNT, 1)//activityId从小到大排序
    let treasureHuntDataArray: TreasureHuntData[] = [];
    let { createTime } = await RoleModel.findByRoleId(roleId);
    for (let obj of activityArray) {
        treasureHuntDataArray.push(new TreasureHuntData(obj, createTime));
    }
    let isOver = false;
    let huntBeginTime = moment(oldHuntEndTime).add(1, 'd').startOf('d').toDate();
    let curDate = moment(new Date()).toDate()

    let index = treasureHuntDataArray.findIndex(obj => { return obj && obj.activityId === oldHuntActivityId });
    for (; index < treasureHuntDataArray.length; index++) {
        let data = treasureHuntDataArray[index];
        let endTime = moment(huntBeginTime).add(data.day, 'd').toDate();
        if (huntBeginTime < curDate && curDate < endTime) {
            huntEndTime = moment(endTime).add(-1, 'm').toDate()
            huntActivityId = data.activityId;
            isOver = true;
        } else {
            huntBeginTime = endTime;
        }
    }

    while (!isOver) {
        huntRoundIndex++;
        for (let data of treasureHuntDataArray) {
            let endTime = moment(huntBeginTime).add(data.day, 'd').toDate();
            if (huntBeginTime < curDate && curDate < endTime) {
                huntEndTime = moment(endTime).add(-1, 'm').toDate()
                huntActivityId = data.activityId;
                isOver = true;
            } else {
                huntBeginTime = endTime;
            }
        }
        if (huntRoundIndex >= 365) {//max
            isOver = true;
        }
    }
    return { huntActivityId, huntBeginTime, huntEndTime, huntRoundIndex }
}


/**
   * 购买每日物资
   *
   * @param {number} serverId 区Id
   * @param {number} activityId 活动Id
   * @param {string} roleId 角色Id
   * @param {string} productID 商品ID
   *
   */
export async function makeShop(roleId: string, roleName: string, sid: string, serverId: number, funcs: number[],
    activityId: number, productID: string) {
    // let activityData: ActivityModelType = await ActivityModel.findActivity(activityId);
    let { huntActivityId, huntBeginTime, huntEndTime, huntRoundIndex, activityData } = await getTreasureHuntData(serverId, roleId);
    if (!activityData) {
        return {
            code: STATUS.ACTIVITY_MISSING,
        }
    }

    let playerData = await getPlayerTreasureHuntShopData(activityId, serverId, roleId, huntRoundIndex, huntBeginTime, huntEndTime,);
    if (!playerData) {
        return {
            code: STATUS.ACTIVITY_MISSING,
        }
    }

    let item = playerData.shop.findProductID(productID)

    if (!item) {
        return {
            code: STATUS.ACTIVITY_MISSING,
        }
    }
    if (item.buyCount >= item.countMax) {
        return {
            code: STATUS.ACTIVITY_MAX_COUNT,
        }
    }
    let cellIndex = item.cellIndex;

    //添加购买记录
    await ActivityTreasureHuntShopModel.buyShopRecord(activityId, roleId, huntRoundIndex, playerData.todayIndex, cellIndex);

    let rewardParamArr: Array<RewardParam> = stringToRewardParam(item.reward);
    let result = await addReward(roleId, roleName, sid, serverId, funcs, rewardParamArr)

    item.buyCount += 1;
    return {
        code: 0,
        data: Object.assign(result, { item })
    }
}