const { TIMES } = require('./constants');
const { removeTier } = require('./utils');

function none() {
    return {
        animSource: null,
        animTarget: null,
    };
}

function getObjects(resolution, game, account) {
    if (!resolution) return none();
    if (!resolution.target) return none();

    const [type, event] = resolution.event;
    if (!event || !event.skill) return none();

    const playerTeam = game.players.find(t => t.id === account.id);
    const playerTeamIds = playerTeam.constructs.map(c => c.id);
    const otherTeam = game.players.find(t => t.id !== account.id);
    const otherTeamIds = otherTeam.constructs.map(c => c.id);
    const sourceIsPlayer = playerTeamIds.includes(resolution.source.id);
    const targetIsPlayer = playerTeamIds.includes(resolution.target.id);

    const targetting = () => {
        if (type === 'AoeSkill') {
            if (targetIsPlayer) return playerTeamIds;
            return otherTeamIds;
        }
        return [resolution.target.id];
    };

    const sameTeam = (sourceIsPlayer && targetIsPlayer) || (!sourceIsPlayer && !targetIsPlayer);
    let y = 0;
    if (!sameTeam) y = targetIsPlayer ? 1 : -1;

    const i = sourceIsPlayer
        ? playerTeamIds.findIndex(c => c === resolution.source.id)
        : otherTeamIds.findIndex(c => c === resolution.source.id);

    const j = targetIsPlayer
        ? playerTeamIds.findIndex(c => c === resolution.target.id)
        : otherTeamIds.findIndex(c => c === resolution.target.id);
    const x = j - i;
    const direction = { x, y };
    // const targetTeam = targetIsPlayer ? playerTeamIds : otherTeamIds;

    const createSourceAnim = () => {
        return {
            animation: 'sourceCast',
            constructId: resolution.source.id,
            direction,
        };
    };

    const skipSource = !resolution.stages.includes('START_SKILL')
        || resolution.source.id === resolution.target.id;

    const animSource = skipSource
        ? null
        : createSourceAnim();

    const animTarget = {
        skill: event.skill,
        constructId: targetting(),
        player: playerTeamIds.includes(resolution.target.id),
        direction,
    };
    return {
        animSource,
        animTarget,
        animSkill: event.skill,
    };
}

function getTime(stages) {
    let time = 0;
    if (stages.includes('START_SKILL') && stages.includes('END_SKILL')) {
        time += TIMES.SOURCE_AND_TARGET_TOTAL_DURATION;
    } else {
        if (stages.includes('START_SKILL')) time += TIMES.SOURCE_DURATION_MS;
        if (stages.includes('END_SKILL')) time += TIMES.TARGET_DURATION_MS;
    }
    if (stages.includes('POST_SKILL')) time += TIMES.POST_SKILL_DURATION_MS;

    return time;
}

function getFocusTargets(resolution, game) {
    if (!resolution) return [];
    if (!resolution.event) return [];
    const [type] = resolution.event;
    const source = resolution.source.id;
    const target = resolution.target.id;

    if (type === 'AoeSkill') {
        const targetTeam = game.players.find(t => t.constructs.find(c => c.id === target));
        const targetTeamIds = targetTeam.constructs.map(c => c.id);
        if (source !== target) targetTeamIds.push(source);
        return targetTeamIds;
    }
    if (source !== target) return [source, target];
    return [target];
}

function getText(resolution) {
    const nullText = { text: null, constructId: null, life: null };
    if (!resolution) return nullText;
    if (!resolution.stages.includes('POST_SKILL')) return nullText;

    function generatePostSkill() {
        const [type, event] = resolution.event;
        if (type === 'Ko') {
            return { text: 'KO!', css: 'ko' };
        }

        if (type === 'Disable') {
            const { disable } = event;
            return { text: `${disable}`, css: '' };
        }

        if (type === 'Immunity') {
            return { text: 'IMMUNE', css: '' };
        }

        if (type === 'Damage') {
            const { mitigation, colour } = event;
            let { amount } = event;
            let css = '';
            if (colour === 'Green') {
                css = 'green-damage';
                amount *= -1;
            }
            if (colour === 'Red') css = 'red-damage';
            if (colour === 'Blue') css = 'blue-damage';

            const mitigationText = mitigation
                ? `(${mitigation})`
                : '';
            return { text: `${amount} ${mitigationText}`, css };
        }

        if (type === 'Healing') {
            const { amount, overhealing } = event;
            return { text: `${amount} (${overhealing} OH)`, css: 'green-damage' };
        }

        if (type === 'Inversion') {
            return { text: 'INVERT', css: '' };
        }

        if (type === 'Reflection') {
            return { text: 'REFLECT', css: '' };
        }

        if (type === 'Effect') {
            const { effect, duration, construct_effects: effects } = event;
            return { text: `+ ${effect} ${duration}T`, css: '', effects };
        }

        if (type === 'Recharge') {
            const { red, blue } = event;
            if (red > 0 && blue > 0) return { text: [`+${red}R +${blue}B`, ''], css: 'purple-damage' };
            if (red > 0) return { text: [`+${red}R`, ''], css: 'red-damage' };
            if (blue > 0) return { text: [`+${blue}B`, ''], css: 'blue-damage' };
            return nullText;
        }

        if (type === 'Removal') {
            const { effect, construct_effects: effects } = event;
            return { text: `-${effect}`, css: '', effects };
        }
        return false;
    }

    const { green, red, blue } = resolution.target;
    const { text, css, effects } = generatePostSkill();
    return {
        css,
        text,
        effects,
        life: { green, red, blue },
        constructId: resolution.target.id,
    };
}

function isCbAnim(skill) {
    return ['Attack', 'Blast', 'Siphon', 'SiphonTick', 'Strike', 'Chaos', 'Slay', 'Heal',
        'Buff', 'Amplify', 'Haste', 'Triage', 'TriageTick', 'Link', 'Hybrid', 'Intercept',
        'Debuff', 'Curse', 'Decay', 'DecayTick', 'Purge', 'Silence', 'Restrict',
        'Stun', 'Bash', 'Absorb', 'Sleep', 'Break', 'Ruin',
        'Block', 'Sustain', 'Electrify', 'Electrocute', 'ElectrocuteTick',
        'Counter', 'CounterAttack', 'Purify', 'Recharge', 'Reflect'].includes(removeTier(skill));
}

module.exports = {
    getFocusTargets,
    getObjects,
    getTime,
    getText,
    isCbAnim,
};
