const { connect } = require('preact-redux');
const preact = require('preact');
const range = require('lodash/range');

const shapes = require('./shapes');
const { STATS } = require('../utils');
const { ConstructAvatar } = require('./construct');
const actions = require('../actions');

const addState = connect(
    function receiveState(state) {
        const { ws, instance, player, account, itemInfo, itemEquip, activeConstruct } = state;

        function sendVboxApply(constructId, i) {
            return ws.sendVboxApply(instance.id, constructId, i);
        }

        function sendUnequip(constructId, item) {
            return ws.sendVboxUnequip(instance.id, constructId, item);
        }

        return {
            instance,
            player,
            account,
            sendVboxApply,
            itemInfo,
            itemEquip,
            activeConstruct,
            sendUnequip,
        };
    },

    function receiveDispatch(dispatch) {
        function quit() {
            dispatch(actions.setInstance(null));
        }

        function setInfo(item) {
            dispatch(actions.setInfo(item));
        }

        function setActiveConstruct(value) {
            dispatch(actions.setActiveConstruct(value));
        }

        function clearInfo() {
            return dispatch(actions.setInfo(null));
        }

        function setItemEquip(v) {
            return dispatch(actions.setItemEquip(v));
        }

        function setItemUnequip(v) {
            return dispatch(actions.setItemUnequip(v));
        }

        return { quit, clearInfo, setInfo, setActiveConstruct, setItemUnequip, setItemEquip };
    }

);

function Construct(props) {
    const {
        activeConstruct,
        itemEquip,
        construct,
        player,
        sendVboxApply,
        setActiveConstruct,
        setItemUnequip,
        setItemEquip,
        itemInfo,
        setInfo,
        sendUnequip,
    } = props;

    function onClick(e) {
        e.stopPropagation();
        e.preventDefault();
        if (itemEquip !== null) sendVboxApply(construct.id, itemEquip);
        setItemEquip(null);
        return setActiveConstruct(construct);
    }

    function hoverInfo(e, info) {
        if (!info) return false;
        e.stopPropagation();
        return setInfo(info);
    }

    const { vbox } = player;
    const skillList = itemInfo.items.filter(v => v.skill).map(v => v.item);
    const specList = itemInfo.items.filter(v => v.spec).map(v => v.item);

    const skills = range(0, 3).map(i => {
        const skill = construct.skills[i];
        const s = skill
            ? skill.skill
            : (<span class="gray">SKILL</span>);

        function skillClick(e) {
            if (!skill) return false;
            setItemUnequip([construct.id, skill.skill]);
            setActiveConstruct(construct);
            e.stopPropagation();
            return true;
        }

        function skillDblClick(e) {
            if (!skill) return false;
            sendUnequip(construct.id, skill.skill);
            setActiveConstruct(null);
            setItemUnequip([]);
            e.stopPropagation();
            e.preventDefault();
            return true;
        }

        // const action = skill ? '' : 'action';
        const equipping = skillList.includes(vbox.bound[itemEquip]) && !skill;
        const classes = `${equipping ? 'equipping' : ''} ${!skill ? 'empty' : ''}`;
        return (
            <button
                key={i}
                disabled={!skill && !equipping}
                class={classes}
                onClick={skillClick}
                onDblClick={skillDblClick}
                onMouseOver={e => hoverInfo(e, skill && skill.skill)} >
                {s}
            </button>
        );
    });

    const specs = range(0, 3).map(i => {
        const s = construct.specs[i];

        if (!s) {
            const equipping = specList.includes(vbox.bound[itemEquip]);
            const classes = `${equipping ? 'equipping' : 'gray'} empty`;
            return (
                <button key={i} class={classes} disabled={!equipping} >
                    {shapes.None()}
                </button>
            );
        }

        const specInfo = itemInfo.items.find(i => i.item === s);

        function specClick(e) {
            e.stopPropagation();
            setItemUnequip([construct.id, s]);
            setActiveConstruct(construct);
        }

        function specDblClick(e) {
            sendUnequip(construct.id, s);
            setActiveConstruct(null);
            setItemUnequip([]);
            e.stopPropagation();
            e.preventDefault();
            return true;
        }


        return (
            <button
                key={i}
                onClick={specClick}
                onDblClick={specDblClick}
                onMouseOver={e => hoverInfo(e, s)} >
                {shapes[s]()}
            </button>
        );
    });

    const stats = Object.keys(STATS).map(s => {
        const stat = STATS[s];

        const info = (s === 'Speed' && 'Speed')
            || (s.includes('Power') && 'Power')
            || (s.includes('Life') && 'Life');

        return <div key={stat.stat}
            alt={stat.stat}
            class={stat.stat}
            onMouseOver={e => hoverInfo(e, info)} >
            {shapes[s]()}
            <div>{construct[stat.stat].value}</div>
        </div>;
    });

    return (
        <div key={construct.id} class="instance-construct" onClick={onClick} >
            <ConstructAvatar construct={construct} />
            <h2 class="name" >{construct.name}</h2>
            <div class="skills" onMouseOver={e => hoverInfo(e, 'constructSkills')} >
                {skills}
            </div>
            <div class="specs" onMouseOver={e => hoverInfo(e, 'constructSpecs')} >
                {specs}
            </div>
            <div class="stats">
                {stats}
            </div>
        </div>
    );
}

function InstanceConstructs(props) {
    const {
        activeConstruct,
        itemEquip,
        player,
        instance,
        // clearInfo,
        setInfo,
        setActiveConstruct,

        sendVboxApply,
        itemInfo,
        setVboxHighlight,
        setItemUnequip,
        setItemEquip,
        sendUnequip,
    } = props;

    if (!player) return false;
    if (instance.phase === 'Lobby') return false;

    const constructs = player.constructs.map((c, i) => Construct({
        construct: c,
        activeConstruct,
        itemEquip,
        setItemUnequip,
        setItemEquip,
        player,
        sendVboxApply,
        setInfo,
        setActiveConstruct,
        itemInfo,
        setVboxHighlight,
        sendUnequip,
    }));

    const classes = `construct-list`;
    return (
        <div class={classes} onClick={() => setActiveConstruct(null)}>
            {constructs}
        </div>
    );
}

module.exports = addState(InstanceConstructs);
