'use strict';

const assert = require('./../../assert');
const common = require('./../../common');

let battle;

describe('Future Sight', () => {
	afterEach(() => {
		battle.destroy();
	});

	it(`should damage in two turns, ignoring Protect, affected by Dark immunities`, () => {
		battle = common.createBattle([[
			{ species: 'Sneasel', moves: ['sleeptalk', 'futuresight'] },
		], [
			{ species: 'Girafarig', moves: ['sleeptalk', 'futuresight', 'protect'] },
		]]);

		const sneasel = battle.p1.active[0];
		const girafarig = battle.p2.active[0];
		battle.makeChoices('move futuresight', 'move futuresight');
		assert.fullHP(girafarig);
		battle.makeChoices();
		assert.fullHP(girafarig);
		battle.makeChoices('auto', 'move protect');
		assert.fullHP(sneasel);
		assert.false.fullHP(girafarig);
	});

	it(`should fail when already active for the target's position`, () => {
		battle = common.createBattle([[
			{ species: 'Sneasel', moves: ['sleeptalk'] },
		], [
			{ species: 'Girafarig', moves: ['futuresight'] },
		]]);

		battle.makeChoices();
		battle.makeChoices();
		assert(battle.log[battle.lastMoveLine + 1].startsWith('|-fail|'));
	});

	it(`[Gen 2] should damage in two turns, ignoring Protect`, () => {
		battle = common.gen(2).createBattle([[
			{ species: 'Sneasel', moves: ['sleeptalk', 'futuresight', 'sweetscent'] },
		], [
			{ species: 'Girafarig', moves: ['sleeptalk', 'futuresight', 'protect', 'sweetscent'] },
		]]);

		const sneasel = battle.p1.active[0];
		const girafarig = battle.p2.active[0];
		battle.makeChoices('move sweetscent', 'move sweetscent'); // counteract imperfect accuracy
		battle.makeChoices('move futuresight', 'move futuresight');
		assert.fullHP(girafarig);
		battle.makeChoices('auto', 'auto');
		assert.fullHP(girafarig);
		battle.makeChoices('auto', 'move Protect');
		assert.false.fullHP(sneasel);
		assert.false.fullHP(girafarig);
	});

	it(`should not double Stomping Tantrum for exiting normally`, () => {
		battle = common.createBattle([[
			{ species: 'Wynaut', moves: ['futuresight', 'stompingtantrum'] },
		], [
			{ species: 'Scizor', ability: 'shellarmor', moves: ['sleeptalk'] },
		]]);

		battle.makeChoices();
		battle.makeChoices('move stompingtantrum', 'move sleeptalk');
		const scizor = battle.p2.active[0];
		const damage = scizor.maxhp - scizor.hp;
		assert.bounded(damage, [19, 23]); // If it were doubled, would be 38-45
	});

	it(`should not trigger Eject Button`, () => {
		battle = common.createBattle([[
			{ species: 'Wynaut', moves: ['futuresight'] },
		], [
			{ species: 'Scizor', item: 'ejectbutton', moves: ['sleeptalk'] },
			{ species: 'Roggenrola', moves: ['sleeptalk'] },
		]]);

		for (let i = 0; i < 3; i++) battle.makeChoices();
		assert.equal(battle.requestState, 'move');
	});

	it(`should be able to set Future Sight against an empty target slot`, () => {
		battle = common.createBattle([[
			{ species: 'Shedinja', moves: ['finalgambit'] },
			{ species: 'Roggenrola', moves: ['sleeptalk'] },
		], [
			{ species: 'Wynaut', moves: ['sleeptalk', 'futuresight'] },
		]]);

		battle.makeChoices('auto', 'move future sight');
		battle.makeChoices('switch 2');
		battle.makeChoices();
		battle.makeChoices();
		const roggenrola = battle.p1.active[0];
		assert.false.fullHP(roggenrola);
	});

	it(`its damaging hit should not count as copyable for Copycat`, () => {
		battle = common.createBattle([[
			{ species: 'Wynaut', moves: ['sleeptalk', 'futuresight'] },
		], [
			{ species: 'Liepard', moves: ['sleeptalk', 'copycat'] },
		]]);

		battle.makeChoices('move futuresight', 'auto');
		battle.makeChoices();
		battle.makeChoices();
		battle.makeChoices('auto', 'move copycat'); // Should fail due to last move being Sleep Talk
		battle.makeChoices();
		battle.makeChoices();
		const wynaut = battle.p1.active[0];
		assert.fullHP(wynaut);
	});

	it(`should only cause the user to take Life Orb recoil on its damaging turn`, () => {
		battle = common.createBattle([[
			{ species: 'wynaut', item: 'lifeorb', moves: ['futuresight'] },
		], [
			{ species: 'mew', moves: ['sleeptalk'] },
		]]);

		battle.makeChoices();
		const wynaut = battle.p1.active[0];
		const mew = battle.p2.active[0];
		assert.fullHP(wynaut, `Wynaut should not take Life Orb recoil on Future Sight's starting turn`);
		battle.makeChoices();
		battle.makeChoices();
		assert.equal(wynaut.hp, wynaut.maxhp - Math.floor(wynaut.maxhp / 10), `Wynaut should take Life Orb recoil on Future Sight's damaging turn`);
		const damage = mew.maxhp - mew.hp;
		assert.bounded(damage, [30, 35]); // 22-27 if Life Orb was not applied
	});

	it(`[Gen 4] should not be affected by Life Orb`, () => {
		battle = common.gen(4).createBattle([[
			{ species: 'wynaut', item: 'lifeorb', moves: ['futuresight'] },
		], [
			{ species: 'mew', ability: 'noguard', moves: ['sleeptalk'] },
		]]);

		battle.makeChoices();
		const wynaut = battle.p1.active[0];
		const mew = battle.p2.active[0];
		battle.makeChoices();
		battle.makeChoices();
		assert.fullHP(wynaut, `Wynaut should not have taken any damage`);
		const damage = mew.maxhp - mew.hp;
		assert.bounded(damage, [21, 25]); // [27-32] if Life Orb was applied
	});

	it(`should not be affected by Life Orb if not the original user`, () => {
		battle = common.createBattle([[
			{ species: 'wynaut', item: 'lifeorb', moves: ['futuresight'] },
			{ species: 'liepard', item: 'lifeorb', moves: ['sleeptalk'] },
		], [
			{ species: 'mew', moves: ['sleeptalk'] },
		]]);

		battle.makeChoices();
		const liepard = battle.p1.pokemon[1];
		const mew = battle.p2.active[0];
		battle.makeChoices();
		battle.makeChoices('switch 2', 'move sleeptalk');
		assert.fullHP(liepard, `liepard should not have taken any damage`);
		const damage = mew.maxhp - mew.hp;
		assert.bounded(damage, [22, 27]); // 30, 35 if Life Orb was applied
	});

	it(`should not cause the user to change typing on either its starting or damaging turn`, () => {
		battle = common.createBattle([[
			{ species: 'roggenrola', ability: 'protean', moves: ['futuresight', 'sleeptalk'] },
		], [
			{ species: 'mew', moves: ['sleeptalk'] },
		]]);

		const roggenrola = battle.p1.active[0];
		battle.makeChoices();
		assert.false(roggenrola.hasType('Psychic'), `Protean Roggenrola should not change type on Future Sight's starting turn`);
		battle.makeChoices();
		battle.makeChoices();
		assert.false(roggenrola.hasType('Psychic'), `Protean Roggenrola should not change type on Future Sight's damaging turn`);
	});

	it(`should be boosted by Terrain only if Terrain is active on the damaging turn`, () => {
		battle = common.createBattle([[
			{ species: 'Blissey', ability: 'shellarmor', moves: ['softboiled'] },
		], [
			{ species: 'Wynaut', ability: 'psychicsurge', moves: ['sleeptalk', 'futuresight'] },
		]]);

		battle.makeChoices('auto', 'move futuresight');
		battle.makeChoices();
		battle.makeChoices();
		const blissey = battle.p1.active[0];
		let damage = blissey.maxhp - blissey.hp;
		assert.bounded(damage, [46, 55]);

		battle.makeChoices('auto', 'move futuresight');
		battle.makeChoices();
		battle.makeChoices();
		damage = blissey.maxhp - blissey.hp;
		assert.bounded(damage, [36, 43]);
	});

	it(`should be boosted by Terrain even if the user is not on the field, as long as the user is not Flying-type`, () => {
		battle = common.createBattle([[
			{ species: 'Blissey', ability: 'shellarmor', moves: ['softboiled'] },
		], [
			{ species: 'cresselia', ability: 'levitate', moves: ['sleeptalk', 'futuresight'] },
			{ species: 'deino', ability: 'psychicsurge', moves: ['sleeptalk'] },
			{ species: 'xatu', moves: ['sleeptalk', 'futuresight'] },
		]]);

		// Cresselia will be Terrain-boosted because its Ability is not checked while not active
		battle.makeChoices('auto', 'move futuresight');
		battle.makeChoices();
		battle.makeChoices('auto', 'switch deino');
		const blissey = battle.p1.active[0];
		let damage = blissey.maxhp - blissey.hp;
		assert.bounded(damage, [102, 121]);

		// Xatu won't be Terrain-boosted because its Flying-type is checked while not active
		battle.makeChoices('auto', 'switch xatu');
		battle.makeChoices('auto', 'move futuresight');
		battle.makeChoices();
		battle.makeChoices('auto', 'switch deino');
		damage = blissey.maxhp - blissey.hp;
		assert.bounded(damage, [96, 114]);
	});

	it(`should not ignore the target's screens, even when the user is not active on the field`, () => {
		battle = common.createBattle([[
			{ species: 'Blissey', ability: 'shellarmor', item: 'lightclay', moves: ['softboiled', 'lightscreen'] },
		], [
			{ species: 'Wynaut', moves: ['sleeptalk', 'futuresight'] },
			{ species: 'deino', moves: ['sleeptalk'] },
		]]);

		battle.makeChoices('move lightscreen', 'move futuresight');
		battle.makeChoices();
		battle.makeChoices();
		const blissey = battle.p1.active[0];
		let damage = blissey.maxhp - blissey.hp;
		assert.bounded(damage, [18, 21]);

		battle.makeChoices('auto', 'move futuresight');
		battle.makeChoices();
		battle.makeChoices('auto', 'switch 2');
		damage = blissey.maxhp - blissey.hp;
		assert.bounded(damage, [18, 21]);
	});

	it(`should not consider the user's item or Ability when the user is not active`, () => {
		battle = common.createBattle([[
			{ species: 'Blissey', ability: 'shellarmor', moves: ['softboiled'] },
		], [
			{ species: 'Wynaut', ability: 'adaptability', item: 'choicespecs', moves: ['futuresight'] },
			{ species: 'Deino', ability: 'powerspot', moves: ['sleeptalk'] },
		]]);

		for (let i = 0; i < 3; i++) battle.makeChoices();
		const blissey = battle.p1.active[0];
		let damage = blissey.maxhp - blissey.hp;
		assert.bounded(damage, [70, 84]); // boosted by Adaptability and Choice Specs

		battle.makeChoices();
		battle.makeChoices();
		battle.makeChoices('auto', 'switch 2');
		damage = blissey.maxhp - blissey.hp;
		assert.bounded(damage, [46, 55]); // only boosted by Power Spot
	});

	it(`should not ignore the target's Unaware`, () => {
		battle = common.createBattle([[
			{ species: 'Manaphy', ability: 'simple', moves: ['tailglow', 'futuresight'] },
		], [
			{ species: 'Ho-Oh', ability: 'unaware', moves: ['luckychant'] },
		]]);

		battle.makeChoices();
		battle.makeChoices('move futuresight', 'auto');
		battle.makeChoices();
		battle.makeChoices();
		const hooh = battle.p2.active[0];
		const damage = hooh.maxhp - hooh.hp;
		assert.bounded(damage, [60, 71]); // Damage would be 236-278 if Unaware was being ignored
	});

	it(`should use the user's most recent Special Attack stat if the user is on the field`, () => {
		battle = common.createBattle([[
			{ species: 'Aegislash', ability: 'stancechange', moves: ['futuresight', 'kingsshield'] },
		], [
			{ species: 'Ho-Oh', ability: 'shellarmor', moves: ['recover'] },
		]]);

		for (let i = 0; i < 3; i++) battle.makeChoices();
		const hooh = battle.p2.active[0];
		let damage = hooh.maxhp - hooh.hp;
		assert.bounded(damage, [79, 94]); // Blade Forme damage

		battle.makeChoices();
		battle.makeChoices('move kingsshield', 'auto');
		battle.makeChoices('move kingsshield', 'auto');
		damage = hooh.maxhp - hooh.hp;
		assert.bounded(damage, [34, 41]); // Shield Forme damage
	});

	it.skip(`should use the user's most recent Special Attack stat, even if the user is not on the field`, () => {
		battle = common.createBattle([[
			{ species: 'Aegislash', ability: 'stancechange', moves: ['futuresight', 'kingsshield'] },
			{ species: 'Wynaut', moves: ['sleeptalk'] },
		], [
			{ species: 'Ho-Oh', ability: 'shellarmor', moves: ['recover', 'flareblitz'] },
		]]);

		battle.makeChoices();
		battle.makeChoices('switch wynaut', 'auto');
		battle.makeChoices();
		const hooh = battle.p2.active[0];
		let damage = hooh.maxhp - hooh.hp;
		assert.bounded(damage, [79, 94], `Future Sight should deal Blade Forme damage, even though Aegislash switched out in Blade Forme`);

		battle.makeChoices('switch aegislash', 'auto');
		battle.makeChoices();
		battle.makeChoices('auto', 'move flareblitz');
		battle.makeChoices(); // switch in Wynaut
		battle.makeChoices();
		damage = hooh.maxhp - hooh.hp;
		assert.bounded(damage, [79, 94], `Future Sight should deal Blade Forme damage, even though Aegislash was KOed in Blade Forme.`);
	});

	it(`should only use Sp. Atk stat boosts/drops if the user is on the field`, () => {
		battle = common.createBattle([[
			{ species: 'Flapple', moves: ['futuresight', 'nastyplot', 'sleeptalk'] },
			{ species: 'Wynaut', moves: ['sleeptalk'] },
		], [
			{ species: 'Ho-Oh', ability: 'shellarmor', moves: ['recover'] },
		]]);

		battle.makeChoices();
		battle.makeChoices('move nastyplot', 'auto');
		battle.makeChoices();
		const hooh = battle.p2.active[0];
		let damage = hooh.maxhp - hooh.hp;
		assert.bounded(damage, [113, 134], `Future Sight should deal damage with +2 Sp. Atk`);

		battle.makeChoices();
		battle.makeChoices('switch wynaut', 'auto');
		battle.makeChoices();
		damage = hooh.maxhp - hooh.hp;
		assert.bounded(damage, [57, 68], `Future Sight should deal damage with +0 Sp. Atk`);
	});

	it(`should never resolve when used on turn 254 or later`, () => {
		battle = common.createBattle([[
			{ species: 'Wynaut', moves: ['sleeptalk', 'futuresight'] },
		], [
			{ species: 'Stakataka', moves: ['sleeptalk'] },
		]]);

		battle.turn = 255; // Showdown turn is +1 from what the games are; this would ordinarily be 254
		battle.makeChoices('move futuresight', 'auto');
		for (let i = 0; i < 5; i++) battle.makeChoices();
		battle.makeChoices('move futuresight', 'auto');
		for (let i = 0; i < 5; i++) battle.makeChoices();

		const stak = battle.p2.active[0];
		assert.fullHP(stak, `Future Sight should have never resolved.`);
	});

	it(`should target particular slots in Doubles`, () => {
		battle = common.createBattle({ gameType: 'doubles' }, [[
			{ species: 'Wynaut', moves: ['sleeptalk', 'futuresight'] },
			{ species: 'Steelix', moves: ['sleeptalk'] },
		], [
			{ species: 'Girafarig', moves: ['sleeptalk', 'recover'] },
			{ species: 'Farigiraf', moves: ['sleeptalk', 'recover'] },
		]]);

		battle.makeChoices('move futuresight 2, auto', 'auto');
		battle.makeChoices();
		battle.makeChoices();
		const giraf = battle.p2.active[0];
		const farig = battle.p2.active[1];
		assert.false.fullHP(farig, `Farigiraf should have been damaged by the 1st Future Sight.`);

		battle.makeChoices('move futuresight 1, auto', 'move recover, move recover');
		battle.makeChoices();
		battle.makeChoices();
		assert.false.fullHP(giraf, `Girafarig should have been damaged by the 2nd Future Sight.`);

		battle.makeChoices('move futuresight -2, auto', 'auto');
		battle.makeChoices();
		battle.makeChoices();

		const steelix = battle.p1.active[1];
		assert.false.fullHP(steelix, `Steelix should have been damaged by the 3rd Future Sight`);
	});

	it(`should do nothing if no Pokemon is present to take damage from the Future attack`, () => {
		battle = common.createBattle([[
			{ species: 'Wynaut', ability: 'magicguard', moves: ['sleeptalk'] },
			{ species: 'Shedinja', moves: ['sleeptalk'] },
		], [
			{ species: 'Happiny', moves: ['stealthrock', 'futuresight'] },
		]]);

		battle.makeChoices('auto', 'move futuresight');
		battle.makeChoices('auto', 'move stealthrock');
		battle.makeChoices('switch 2', 'auto');
		battle.makeChoices('switch 2');
		battle.makeChoices();
		const wynaut = battle.p1.active[0];
		assert.fullHP(wynaut);
	});
});
