const { eachSeries } = require('async');

const CombatAnimations = require('./combat.animations');
const {
    DELAYS: { ANIMATION_DURATION, MOVE_CREEP, DAMAGE_TICK },
    POSITIONS: { COMBAT },
} = require('./constants');

function findResolutionCryps(scene, group, resolution, game) {
    const sourceSpawn = group.children.entries.find(c => c.cryp.id === resolution.source.id);

/*    const sourceCryp = game.teams.find(t => t.cryps.find(c => c.id === resolution.source_cryp_id))
        .cryps.find(c => c.id === resolution.source_cryp_id);

    const targetCryp = game.teams.find(t => t.cryps.find(c => c.id === resolution.target_cryp_id))
        .cryps.find(c => c.id === resolution.target_cryp_id);
*/
    const targetSpawn = group.children.entries.find(c => c.cryp.id === resolution.target.id);

    return { sourceSpawn, targetSpawn };
}

function calculateTweenParams(sourceSpawn, targetSpawn, account, skill) {
    const tweenParams = (targets, centreSpot) => {
        const enemy = targets.cryp.account !== account.id;
        let x = centreSpot ? COMBAT.width() * 0.3 : targets.x;
        x = (enemy && centreSpot) ? x + COMBAT.width() * 0.4 : x;
        const y = centreSpot ? COMBAT.height() * 13.25 / 35 : targets.y;
        const ease = 'Power1';
        const duration = MOVE_CREEP;
        return {
            targets, x, y, ease, duration,
        };
    };
    let moveSourceBattle = false;
    let moveSourceOrig = false;
    const targetOnlySkill = ['DecayTick'];
    if (!(targetOnlySkill.includes(skill))) {
        if (sourceSpawn.cryp.account !== targetSpawn.cryp.account) {
            moveSourceBattle = tweenParams(sourceSpawn, true);
            moveSourceOrig = tweenParams(sourceSpawn, false);
        }
    }

    const moveTargetBattle = tweenParams(targetSpawn, true);
    const moveTargetOrig = tweenParams(targetSpawn, false);

    return {
        moveSourceBattle, moveSourceOrig, moveTargetBattle, moveTargetOrig,
    };
}

function animatePhase(scene, game, resolution, cb) {
    // return early for disabled skills
    if (resolution.length === 0) return cb();
    if (resolution.event[0] === 'Disable'
        || resolution.event[0] === 'TargetKo'
        || resolution.event === 'Ko') return cb();

    const group = scene.scene.get('CombatCryps').cryps;
    const animations = new CombatAnimations(scene);
    const account = scene.registry.get('account');

    // Find cryps, targets
    const { sourceSpawn, targetSpawn } = findResolutionCryps(scene, group, resolution, game);
    const {
        moveSourceBattle, moveSourceOrig, moveTargetBattle, moveTargetOrig,
    } = calculateTweenParams(sourceSpawn, targetSpawn, account, resolution.event[1].skill);

    const castParams = () => {
        const x = (sourceSpawn === targetSpawn) ? moveTargetBattle.x : sourceSpawn.x;
        const y = (sourceSpawn === targetSpawn) ? moveTargetBattle.y : sourceSpawn.y;
        return { x, y };
    };
    const castLocation = castParams();

    // Move cryps into position
    if (moveSourceBattle) scene.tweens.add(moveSourceBattle);
    scene.tweens.add(moveTargetBattle);

    return scene.time.delayedCall(MOVE_CREEP, () => {
        const sourceAlly = sourceSpawn.cryp.account === account.id;
        const targetAlly = targetSpawn.cryp.account === account.id;
        // animate animation
        animations.getSkill(resolution.event[1].skill, sourceAlly, targetAlly, castLocation);
        // Target cryp takes damage
        scene.time.delayedCall(ANIMATION_DURATION, () => {
            console.log(resolution);
            if (resolution.event[0] === 'Damage') {
                targetSpawn.takeDamage(resolution.event[1]);
                scene.registry.set('gameLog', scene.registry.get('gameLog') + 1);
            }
            if (resolution.event[0] === 'Healing') {
                targetSpawn.takeHealing(resolution.event[1]);
                scene.registry.set('gameLog', scene.registry.get('gameLog') + 1);
            }
            if (resolution.event[0] === 'Effect') {
                targetSpawn.effects.addEffect(resolution.event[1]);
                console.log('target has new effect', resolution.event[1].effect);
            }

            if (resolution.event[0] === 'Removal') {
                targetSpawn.effects.removeEffect(resolution.event[1].effect);
                console.log('target effect removed', resolution.event[1].effect);
            }
            if (moveSourceOrig) scene.tweens.add(moveSourceOrig);
            scene.tweens.add(moveTargetOrig);

            // all done
            scene.time.delayedCall(MOVE_CREEP, () => {
                animations.destroy(true);
                return cb();
            });
        });
    });
}

function renderResolutions(scene, game, resolutions) {
    scene.registry.set('gamePhase', 'animating');
    scene.registry.set('gameLog', scene.registry.get('gameLog') + 1);

    eachSeries(
        resolutions,
        (resolution, cb) => animatePhase(scene, game, resolution, cb),
        (err) => {
            if (err) return console.error(err);
            scene.registry.set('gamePhase', 'Skill');
            return true;
        }
    );

    return true;
}

module.exports = renderResolutions;
