const { connect } = require('preact-redux');
const { Component } = require('preact');
const preact = require('preact');
const range = require('lodash/range');
const reactStringReplace = require('react-string-replace');

const { STATS, removeTier } = require('../utils');
const { ConstructAvatar, ConstructText } = require('./construct');
const shapes = require('./shapes');
const { INFO } = require('./../constants');
const actions = require('../actions');

const SkillBtn = require('./skill.btn');

const addStateText = connect(({ animText, itemInfo }) => ({ animText, itemInfo }));

class combatText extends preact.Component {
    shouldComponentUpdate(newProps) {
        if (newProps.animText !== this.props.animText) return true;
        return false;
    }

    render(props) {
        const { construct, animText, itemInfo } = props;
        if (animText && animText.constructId === construct.id) {
            const itemSource = itemInfo.combos.filter(c => c.item === removeTier(animText.skill));
            const itemSourceInfo = itemSource.length
                ? `${itemSource[0].components[0]} ${itemSource[0].components[1]} ${itemSource[0].components[2]}`
                : false;
            const itemRegEx = /(Red|Blue|Green)/;
            const itemSourceDescription = reactStringReplace(itemSourceInfo, itemRegEx, match => shapes[match]());

            return (
                <div class="combat-text">
                    <h2>
                        <span>{animText.skill}</span>
                    </h2>
                    <span>{itemSourceDescription}</span>
                    <h1 class={animText.css}>
                        <span>{animText.text}</span>
                    </h1>
                </div>
            );
        }
        return null;
    }
}

const ConstructAnimationText = addStateText(combatText);

const addState = connect(
    function receiveState(state) {
        const {
            ws,
            game,
            account,
            activeSkill,
            animFocus,
            animating,
            animText,
            gameSkillInfo,
            itemInfo,
            tutorialGame,
        } = state;

        function selectSkillTarget(targetConstructId) {
            if (activeSkill) {
                return ws.sendGameSkill(game.id, activeSkill.constructId, targetConstructId, activeSkill.skill);
            }
            return false;
        }

        return {
            game,
            account,
            animating,
            animFocus,
            animText,
            activeSkill,
            selectSkillTarget,
            gameSkillInfo,
            itemInfo,
            tutorialGame,
        };
    },

    function receiveDispatch(dispatch) {
        function setGameEffectInfo(info) {
            dispatch(actions.setGameEffectInfo(info));
        }

        function setTutorialGameClear(activeSkill, tutorialGame) {
            if (activeSkill && tutorialGame) dispatch(actions.setTutorialGame(null));
        }

        return { setGameEffectInfo, setTutorialGameClear };
    }

);

const eventClasses = (animating, animFocus, construct, postSkill) => {
    if (!animating) return '';
    if (!postSkill) {
        if (animFocus.includes(construct.id)) return '';
        return 'unfocus';
    }
    if (postSkill.constructId !== construct.id) {
        if (animFocus.includes(construct.id)) return '';
        return 'unfocus';
    }
    if (postSkill.effects) construct.effects = postSkill.effects;
    construct.green_life.value = postSkill.life.green;
    construct.red_life.value = postSkill.life.red;
    construct.blue_life.value = postSkill.life.blue;
    return postSkill.css;
};

class GameConstruct extends Component {
    constructor() {
        super();
        this.resolvedLength = 0;
    }

    shouldComponentUpdate(newProps) {
        if (newProps.activeSkill !== this.props.activeSkill) return true;
        if (newProps.animFocus !== this.props.animFocus) return true;
        if (newProps.animText !== this.props.animText) return true;
        if (newProps.animating !== this.props.animating) return true;
        if (newProps.construct !== this.props.construct) return true;
        if (newProps.player !== this.props.player) return true;
        if (newProps.tutorialGame !== this.props.tutorialGame) return true;
        if (newProps.gameSkillInfo !== this.props.gameSkillInfo) return true;
        return false;
    }

    render() {
        const {
            // Changing state variables
            activeSkill,
            animFocus,
            animText,
            animating,
            construct,
            player,
            tutorialGame,
            gameSkillInfo,
            // Constants
            i,
            itemInfo,
            // Functions
            selectSkillTarget,
            setTutorialGameClear,
            setGameEffectInfo,
        } = this.props;

        const koEvent = animText ?  animText.text === 'KO!' && animText.constructId === construct.id : false;
        const ko = construct.green_life.value === 0 && !koEvent ? 'ko' : '';
        const classes = eventClasses(animating, animFocus, construct, animText);
        const cssClass = ['ko-transition', 'unfocus'].includes(classes) ? classes : null;

        const stats = ['RedLife', 'GreenLife', 'BlueLife'].map((s, j) => (
            <div key={j} alt={STATS[s].stat}>
                {shapes[s]()}
                <div class="max" >{construct[STATS[s].stat].value} / {construct[STATS[s].stat].max}</div>
                <div class="value" >{construct[STATS[s].stat].value}</div>
            </div>
        ));

        const skills = range(0, 3)
            .map(j => <SkillBtn key={j} construct={construct} i={j} j={i} animating={animating} />);

        let crypSkills = <div></div>;
        if (player) crypSkills = (<div class="skills"> {skills} </div>);

        function hoverInfo(e, info) {
            e.stopPropagation();
            return setGameEffectInfo(info);
        }
        const effectBox = () => {
            if (gameSkillInfo && gameSkillInfo.constructId === construct.id) {
                const fullInfo = itemInfo.items.find(k => k.item === gameSkillInfo.skill) || INFO[gameSkillInfo.skill];
                const regEx = /(RedPower|BluePower|GreenPower|RedLife|BlueLife|GreenLife|SpeedStat)/;
                const infoDescription = reactStringReplace(fullInfo.description, regEx, match => shapes[match]());
                const speed = <span> Speed {shapes.SpeedStat()} multiplier {fullInfo.speed * 4}% </span>;
                return (
                    <div class="skill-description">
                        <h2><span> {gameSkillInfo.skill} </span></h2>
                        <span>{infoDescription} </span> <br />
                        {speed}
                    </div>);
            }
            const effects = construct.effects.length
                ? construct.effects.map(c =>
                    <div key={c.effect}>
                        <span key={c.effect} onMouseOver={e => hoverInfo(e, c)}
                            onMouseOut={e => hoverInfo(e, null)}> {c.effect} - {c.duration}T
                        </span>
                    </div>)
                : null;
            return (<div class="effects"> {effects} </div>);
        };

        return (
            <div
                onClick={() => {
                    selectSkillTarget(construct.id);
                    setTutorialGameClear(activeSkill, tutorialGame);
                }}
                style={ activeSkill ? { cursor: 'pointer' } : {}}
                class={`game-construct ${ko} ${cssClass}`}>
                <div class="left">
                    {crypSkills}
                    {effectBox()}
                </div>
                <div class="right">
                    <div class="stats"> {stats} </div>
                    <ConstructAvatar construct={construct} />
                    <ConstructText construct={construct} />
                    <ConstructAnimationText construct={construct} />
                </div>
            </div>
        );
    }
}

module.exports = addState(GameConstruct);
