import { Client } from './Client';
import 'mocha';
import { PinusWSClient } from 'pinus-robot-plugin';
import { expect } from 'chai';
import { addItemsIfNotEnough, checkBattleGoods, checkDisplayItems, checkSuccessResponse, checkTimeStamp, checkWarJson } from './CheckPatten';
import * as dic7001 from '../app/resource/warJsons/7001.json';
import { DEBUG_MAGIC_WORD } from '../app/consts';

describe.skip('蛮夷入侵测试', function () {
    let pinusClient: PinusWSClient;
    const aid = 1;
    let roleInfo;
    let challengeCnt;

    before(function (done) {
        const c = new Client();
        const timer = setInterval(() => {
            if (c.client) {
                pinusClient = c.client;
                roleInfo = c.roleInfo;
                clearInterval(timer);
                debugStart(pinusClient, aid, () => {
                    done();
                });
            }
        }, 500);
    });

    after(function (done) {
        debugEnd(pinusClient, aid, () => {
            pinusClient.disconnect();
            // disconnect 后等待 500ms，供服务器清理环境、退出频道等
            setTimeout(() => {
                done();
            }, 500);
        });
    });

    it('进入蛮夷入侵界面', function (done) {
        pinusClient.request('guild.gateActivityHandler.getGateActivity', { }, (res) => {
            checkSuccessResponse(res);
            // expect(res.data.status).to.equal(1);
            expect(res.data.time).to.be.a('number');
            expect(res.data.challengeCnt).to.be.a('number');
            challengeCnt = res.data.challengeCnt;
            checkGuildRanks(res.data.guildRank, aid);
            checkGuildRank(res.data.myGuildRank, aid);
            checkMemberRanks(res.data.memberRank);
            checkMemberRank(res.data.myMemberRank);
            done()
        });
    });

    let code;

    it('开启挑战', function (done) {
        if(challengeCnt <= 0) {
            debugIncChallengeCnt(() => {
                checkBattle();
            })
        } else {
            checkBattle();
        }

        function checkBattle() {
            let heroes = getHeroes(roleInfo)
            pinusClient.request('guild.gateActivityHandler.checkBattle', { heroes }, (res) => {
                checkSuccessResponse(res);
                expect(res.data.code).to.be.a('string');
                code = res.data.code;
                expect(res.data.status).to.equal(1);
                expect(res.data.guildScore).to.be.a('number');
                expect(res.data.myScore).to.be.a('number');
                expect(res.data.time).to.be.a('number');
                expect(res.data.challengeCnt).to.equal(challengeCnt - 1);
                challengeCnt = res.data.challengeCnt;
                done();
            });
        }
    });

    it('上报玩家军功', function (done) {

        let round = 1;
        let record = dic7001.filter(cur => cur.relation == 2).map(cur => {
            return { round, dataId: cur.dataId };
        })
        checkEventGateRankUpdate(pinusClient, aid);
        pinusClient.request('guild.gateActivityHandler.action', { code, round, record }, res => {
            checkSuccessResponse(res);
            expect(res.data.code).to.equal(code);
            expect(res.data.status).to.equal(1);
            expect(res.data.guildScore).to.be.a('number');
            expect(res.data.myScore).to.be.a('number');
            expect(res.data.time).to.be.a('number');
            done();
        });

    });

    it('结束挑战', function (done) {
        pinusClient.request('guild.gateActivityHandler.battleEnd', { code, isSuccess: true }, res => {
            checkSuccessResponse(res);
            expect(res.data.code).to.equal(code);
            // expect(res.data.status).to.equal(1);
            expect(res.data.guildScore).to.be.a('number');
            expect(res.data.myScore).to.be.a('number');
            expect(res.data.time).to.be.a('number');
            expect(res.data.info).to.be.an('object');
            expect(res.data.info.round).to.be.a('number');
            expect(res.data.info.enemyCnt).to.be.a('number');
            expect(res.data.info.littleBossCnt).to.be.a('number');
            expect(res.data.info.bossCnt).to.be.a('number');
            expect(res.data.info.isSuccess).to.equal(true);
            done();
        });
    });

    function debugIncChallengeCnt(cb) {
        pinusClient.request('guild.gateActivityHandler.debugIncChallengeCnt', {}, () => {
            challengeCnt = 99;
            cb();
        })
    }
});

function checkEventGateRankUpdate(pinusClient, aid, cb?) {
    pinusClient.on('onGuildGateRankUpdate', (res) => {
        checkSuccessResponse(res);
        checkGuildRanks(res.guildRank, aid);
        checkGuildRank(res.myGuildRank, aid);
        checkMemberRanks(res.memberRank);
        if(cb) cb();
    });
}

function checkGateHpUpdate(pinusClient, originGateHp, cb?) {
    pinusClient.on('onGuildGateHpUpdate', (res) => {
        checkSuccessResponse(res);
        expect(res.data.gateHp).to.lessThan(originGateHp);
        cb(res.data.gateHp);
    });
}

describe.skip('诸侯混战测试', function () {
    let pinusClient: PinusWSClient;
    const aid = 2;
    let roleInfo;

    before(function (done) {
        const c = new Client();
        const timer = setInterval(() => {
            if (c.client) {
                pinusClient = c.client;
                roleInfo = c.roleInfo;
                clearInterval(timer);
                debugStart(pinusClient, aid, () => {
                    done();
                });
            }
        }, 500);
    });

    after(function (done) {
        debugEnd(pinusClient, aid, () => {
            pinusClient.disconnect();
            // disconnect 后等待 500ms，供服务器清理环境、退出频道等
            setTimeout(() => {
                done();
            }, 500);
        });
    });

    let cities;
    let cityId = 1;

    it('进入诸侯混战界面', function (done) {
        pinusClient.request('guild.cityActivityHandler.getCityActivity', { }, res => {
           checkSuccessResponse(res);
        //    expect(res.data.status).to.equal(1);
           expect(res.data.time).to.be.a('number');
           checkCities(res.data.cities);
           cities = res.data.cities;
            done()
        });
    });

    it('获取单个城池状态', function (done) {
        pinusClient.request('guild.cityActivityHandler.getCityStatus', { cityId }, res => {
            checkSuccessResponse(res);
            expect(res.data.cityId).to.equal(cityId);
            // expect(res.data.status).to.equal(1);
            expect(res.data.time).to.be.a('number');
            expect(res.data.cityStatus).to.be.a('number');
            expect(res.data.gateHp).to.be.a('number');
            checkTimeStamp(res.data.challengeTime, 10, true);
            checkGuildRanks(res.data.guildRank, aid);
            checkGuildRank(res.data.myGuildRank, aid);
            checkMemberRanks(res.data.memberRank);
            checkMemberRank(res.data.myMemberRank);

             done()
         });
    });

    it('宣战', function (done) {
        pinusClient.request('guild.cityActivityHandler.declareCity', { cityId }, res => {
            checkSuccessResponse(res);
            checkCities(res.data.cities);
            done()
        });
    });

    let code;

    it('开始挑战', function (done) {
        let heroes = getHeroes(roleInfo);
        checkEventCityRankUpdate(pinusClient, aid);

        pinusClient.request('guild.cityActivityHandler.checkBattle', { cityId, heroes }, res => {
            checkSuccessResponse(res);
            expect(res.data.code).to.be.a('string');
            code = res.data.code;
            expect(res.data.cityId).to.equal(cityId);
            expect(res.data.status).to.equal(1);
            expect(res.data.time).to.be.a('number');
            expect(res.data.cityStatus).to.be.a('number');
            expect(res.data.gateHp).to.be.a('number');
            expect(res.data.guildScore).to.be.a('number');
            expect(res.data.myScore).to.be.a('number');
            done()
        });
    });

    it('上报城门受到伤害', function (done) {
        let hid = roleInfo.heros[0].hid;
        checkCityGateHpUpdate(pinusClient, cityId, () => {
            done()
        })
        pinusClient.request('guild.cityActivityHandler.hitGate', { cityId, code, damage: 1000000, hid, round: 1 }, res => {
            checkSuccessResponse(res);
            expect(res.data.code).to.equal(code);
            expect(res.data.status).to.equal(1);
            expect(res.data.time).to.be.a('number');
            expect(res.data.gateHp).to.be.a('number');
            expect(res.data.guildScore).to.be.a('number');
            expect(res.data.myScore).to.be.a('number');
        });
    });

    it('结束挑战', function (done) {
        pinusClient.request('guild.cityActivityHandler.battleEnd', { cityId, code, isSuccess: true }, res => {
            checkSuccessResponse(res);
            expect(res.data.isSuccess).to.equal(true);
            expect(res.data.code).to.equal(code);
            expect(res.data.status).to.equal(1);
            expect(res.data.time).to.be.a('number');
            expect(res.data.gateHp).to.be.a('number');
            expect(res.data.guildScore).to.be.a('number');
            expect(res.data.myScore).to.be.a('number');
            checkTimeStamp(res.data.challengeTime, 10, true);
            done()
        });
    });
});


function checkEventCityRankUpdate(pinusClient, aid, cb?) {
    pinusClient.on('onGuildCityRankUpdate', (res) => {
        checkSuccessResponse(res);
        checkGuildRanks(res.data.guildRank, aid);
        checkGuildRank(res.data.myGuildRank, aid);
        checkMemberRanks(res.data.memberRank);
        if(cb) cb();
    });
}

function checkCityGateHpUpdate(pinusClient, cityId, cb?) {
    pinusClient.on('onGuildCityGateHpUpdate', (res) => {
        checkSuccessResponse(res);
        expect(res.data.cityId).to.equal(cityId);
        expect(res.data.gateHp).to.be.a('number');
        cb(res.data.gateHp);
    });
}

describe.skip('粮草先行测试', function () {
    let pinusClient: PinusWSClient;
    const aid = 3;
    let roleInfo;

    before(function (done) {
        const c = new Client();
        const timer = setInterval(() => {
            if (c.client) {
                pinusClient = c.client;
                roleInfo = c.roleInfo;
                clearInterval(timer);
                debugStart(pinusClient, aid, () => {
                    done();
                });
            }
        }, 500);
    });

    after(function (done) {
        debugEnd(pinusClient, aid, () => {
            pinusClient.disconnect();
            // disconnect 后等待 500ms，供服务器清理环境、退出频道等
            setTimeout(() => {
                done();
            }, 500);
        });
    });

    it('进入粮草先行界面', function (done) {
        pinusClient.request('guild.raceActivityHandler.getRaceActivity', { }, res => {
            checkSuccessResponse(res);
            // expect(res.data.status).to.equal(1);
            expect(res.data.time).to.be.a('number');
            expect(res.data.hasJoin).to.be.a('boolean');
            checkWoodenHorse(res.data.woodenHorse);
            checkGuildRanks(res.data.guildRank, aid);
            checkGuildRank(res.data.myGuildRank, aid);
             done()
         });
    });

    let code;
    it('加入木马', function (done) {
        checkEventHourseUpdate();
        pinusClient.request('guild.raceActivityHandler.join', { }, res => {
            checkSuccessResponse(res);
            // expect(res.data.status).to.equal(1);
            expect(res.data.code).to.be.a('string');
            code = res.data.code;
            expect(res.data.time).to.be.a('number');
            expect(res.data.hasJoin).to.be.a('boolean');
            checkWoodenHorse(res.data.woodenHorse);
            done()
        });
    });

    it('获取比赛战场', function (done) {
        pinusClient.request('guild.raceActivityHandler.getRace', { }, res => {
            checkSuccessResponse(res);
            expect(res.data.status).to.equal(1);
            expect(res.data.time).to.be.a('number');
            expect(res.data.hasJoin).to.be.a('boolean');
            checkWoodenHorses(res.data.woodenHorseList);
            checkEvents(res.data.events);
            checkDisplayItems(res.data.items);
            done()
        });
    });

    it('结束比赛', function (done) {
        pinusClient.request('guild.raceActivityHandler.settleReward', { magicWord: DEBUG_MAGIC_WORD, serverId: roleInfo.serverId }, res => {
            pinusClient.request('guild.raceActivityHandler.battleEnd', { code, isSuccess: true }, res => {
                checkSuccessResponse(res);
                expect(res.data.hasShow).to.equal(false);
                checkTimeStamp(res.data.timestamp, 13, false);
                checkWoodenHorse(res.data.woodenHorse);
                expect(res.data.myGuildRank).to.be.a('number');
                done()
            });
        });
    });

    function checkWoodenHorses(woodenHorses) {
        expect(woodenHorses).to.be.an('array');
        woodenHorses.forEach(woodenHorse => {
            checkWoodenHorse(woodenHorse)
        })
    }
    function checkWoodenHorse(woodenHorse) {
        expect(woodenHorse.guildCode).to.be.a('string');
        expect(woodenHorse.guildName).to.be.a('string');
        expect(woodenHorse.memberCnt).to.be.a('number');
        expect(woodenHorse.speed).to.be.a('number');
        expect(woodenHorse.durability).to.be.a('number');
        expect(woodenHorse.time).to.be.a('number');
        expect(woodenHorse.guildCe).to.be.a('number');
        expect(woodenHorse.members).to.be.an('array');
        woodenHorse.members.forEach(member => {
            expect(member.roleId).to.be.a('string');
            expect(member.roleName).to.be.a('string');
        })
        expect(woodenHorse.shield).to.be.a('number');
        checkTimeStamp(woodenHorse.shieldTime, 13, true);
        expect(woodenHorse.status).to.be.a('number');
    }

    function checkEvents(events) {
        if(!events) return;
        expect(events).to.be.an('array');
        events.forEach(event => {
            if(event.startTime) checkTimeStamp(event.startTime, 13, true);
            if(event.startDistance) expect(event.startDistance).to.be.a('number');
            expect(event.id).to.be.a('number');
            expect(event.fromGuild).to.be.a('string');
            expect(event.toGuild).to.be.a('string');
        });
    }

    function checkEventHourseUpdate(cb?) {
        pinusClient.on('onRaceHorseUpdate', (res) => {
            checkSuccessResponse(res);
            checkTimeStamp(res.data.timestamp, 13, false);
            checkWoodenHorses(res.data.woodenHorseList);
            checkGuildRanks(res.data.guildRank, aid);
            checkGuildRank(res.data.myGuildRank, aid);
            checkEvents(res.data.memberRank);
            if(cb) cb();
        });
    }

});

function debugStart(pinusClient, aid, cb) {
    checkEventActivityStatus(pinusClient);
    let week = aid == 1? 3: (aid == 2? 2: 1);

    pinusClient.request('guild.gateActivityHandler.debugSetDay', { week }, (res) => {
        pinusClient.request('guild.gateActivityHandler.debugStartActivity', { aid }, (res) => {
            cb();
        });
    });
}

function debugEnd(pinusClient, aid, cb) {
    checkEventActivityEnd(pinusClient);

    pinusClient.request('guild.gateActivityHandler.debugEndActivity', {aid}, res => {
        cb();
    })
}

function checkEventActivityStatus(pinusClient, cb?) {
    pinusClient.on('onGuildActivityStatus', (res) => {
        checkSuccessResponse(res);
        expect(res.data.guildActivities).to.be.an('array');
        res.data.guildActivities.forEach(guildActivity => {
            expect(guildActivity.aid).to.be.a('number');
            expect(guildActivity.status).to.be.a('number');
            expect(guildActivity.time).to.be.a('number');
            expect(guildActivity.isOpen).to.be.a('boolean');
        });
        if(cb) cb();
    });
}

function checkEventActivityEnd(pinusClient, cb?) {
    pinusClient.on('onGuildActivityEnd', (res) => {
        checkSuccessResponse(res);
        if(cb) cb();
    });
}

function checkGuildRanks(guildRanks, aid) {
    expect(guildRanks).to.be.an('array');
    guildRanks.forEach(guildRank => {
        checkGuildRank(guildRank, aid);
    })
}

function checkGuildRank(guildRank, aid) {
    expect(guildRank.rank).to.be.a('number');
    expect(guildRank.code).to.be.a('string');
    expect(guildRank.name).to.be.a('string');
    expect(guildRank.num).to.be.a('number');
    if(aid == 3) {
        expect(guildRank.time).to.be.a('number');
        expect(guildRank.durability).to.be.a('number');
    }
}

function checkMemberRanks(memberRanks) {
    expect(memberRanks).to.be.an('array');
    memberRanks.forEach(memberRank => {
        checkMemberRank(memberRank);
    })
}

function checkMemberRank(memberRank) {
    expect(memberRank.rank).to.be.a('number');
    expect(memberRank.roleId).to.be.a('string');
    expect(memberRank.roleName).to.be.a('string');
    expect(memberRank.num).to.be.a('number');
}

function checkCities(cities) {
    expect(cities).to.be.an('array');
    cities.forEach(city => {
        expect(city.cityId).to.be.a('number');
        expect(city.status).to.be.a('number');
        expect(city.guardGuildCode).to.be.a('string');
        expect(city.guardGuildName).to.be.a('string');
        expect(city.declareCount).to.be.a('number');
    })
}

function getHeroes(roleInfo) {
    let heroes = [];
    for(let i = 0; i < 6; i++) {
        if(roleInfo.heros.length - 1 < i) break;
        heroes.push(roleInfo.heros[i].seqId);
    }
    return heroes
}