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

const shapes = require('./shapes');
const { convertItem } = require('./../utils');
const actions = require('../actions');

const addState = connect(
    function receiveState(state) {
        const {
            ws,
            instance,
            player,
            combiner,
            reclaiming,
            vboxHighlight,
            itemInfo,
        } = state;

        function sendVboxDiscard() {
            return ws.sendVboxDiscard(instance.id);
        }

        function sendVboxAccept(group, index) {
            return ws.sendVboxAccept(instance.id, group, index);
        }

        function sendVboxCombine() {
            return ws.sendVboxCombine(instance.id, combiner);
        }

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

        return {
            combiner,
            instance,
            player,
            reclaiming,
            sendVboxAccept,
            sendVboxCombine,
            sendVboxDiscard,
            sendVboxReclaim,
            vboxHighlight,
            itemInfo,
        };
    },

    function receiveDispatch(dispatch) {
        function setCombiner(c) {
            return dispatch(actions.setCombiner(c));
        }

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

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

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

        return {
            setCombiner,
            setReclaiming,
            setInfo,
            setVboxHighlight,
        };
    }

);

function Vbox(args) {
    const {
        combiner,
        instance,
        itemInfo,
        player,
        reclaiming,
        sendVboxAccept,
        sendVboxCombine,
        sendVboxDiscard,
        sendVboxReclaim,
        vboxHighlight,

        setCombiner,
        setInfo,
        setReclaiming,
        setVboxHighlight,
    } = args;

    if (!player) return false;
    const { vbox } = player;

    // function setHighlight(type) {
    //     if (type === 'skill') return setVboxHighlight(itemInfo.items.filter(v => v.skill).map(v => v.item));
    //     if (type === 'spec') return setVboxHighlight(itemInfo.items.filter(v => v.spec).map(v => v.item));
    //     return false;
    // }

    function combinerChange(newCombiner) {
        setCombiner(newCombiner);
        if (newCombiner.every(c => c === null)) return setVboxHighlight([]);

        const combinerValues = newCombiner.map(cv => player.vbox.bound[cv]).filter(cv => cv);

        const filteredCombos = itemInfo.combos
            .filter(combo => combinerValues.every(u => combo.components.includes(u)));

        const comboValues = itemInfo.items.filter(v => {
            if (!filteredCombos.some(c => c.components.includes(v.item))) return false;
            if (!['Red', 'Green', 'Blue'].includes(v.item) && combinerValues.includes(v.item)) return false;
            return true;
        });

        return setVboxHighlight(comboValues.map(v => v.item));
    }

    //
    // VBOX
    //
    const free = [];
    for (let i = 0; i < 6; i++) {
        free.push([vbox.free[0][i], vbox.free[1][i], vbox.free[2][i]]);
    }

    let vboxTimer;
    const LONG_TOUCH_TIME = 500;
    function vboxTouchStart(e, i, j) {
        vboxTimer = (setTimeout(() => {
            sendVboxAccept(j, i);
            vboxTimer = null;
        }, LONG_TOUCH_TIME));
        return true;
    }

    function vboxTouchEnd(e, i, j) {
        if (vboxTimer) {
            clearTimeout(vboxTimer);
        }
        return true;
    }

    function vboxTouchMove(e) {
        if (vboxTimer) clearTimeout(vboxTimer);
        e.stopPropagation();
        return true;
    }

    function vboxHover(e, v) {
        if (v) {
            setInfo(v);
            e.stopPropagation();
        }
        return true;
    }

    const freeRows = free.map((row, i) => {
        const cells = row.map((c, j) => {
            const highlighted = c && vboxHighlight.includes(c);

            return <td
                key={j}
                class={`${highlighted ? 'highlight' : ''}`}
                onTouchStart={e => vboxTouchStart(e, i, j)}
                onTouchEnd={e => vboxTouchEnd(e, i, j)}
                onTouchMove={e => vboxTouchMove(e)}

                // onClick={freeClick}
                onDblClick={() => sendVboxAccept(j, i) }
                onMouseOver={e => vboxHover(e, c)}
                >
                {convertItem(c)}
            </td>;
        });

        return (
            <tr key={i}>
                {cells}
            </tr>
        );
    });

    //
    //  INVENTORY
    //
    function boundClick(e, i) {
        const value = vbox.bound[i];
        if (reclaiming && value) return sendVboxReclaim(i);
        if (value) {
            const insert = combiner.findIndex(j => j === null);
            if (insert === -1) return combinerChange([i, null, null]);
            combiner[insert] = i;
            return combinerChange(combiner);
        }
        return false;
    }

    const boundTds = range(0, 9).map(i => {
        const value = vbox.bound[i];
        if (combiner.indexOf(i) > -1) {
            return (
                <td
                    key={i}>
                    &nbsp;
                </td>
            );
        }

        const highlighted = value && vboxHighlight.includes(value);

        return (
            <td
                key={i}
                class={`${highlighted ? 'highlight' : ''}`}
                onMouseOver={(e) => vboxHover(e, value)}
                onClick={e => boundClick(e, i, highlighted) }>
                {convertItem(value)}
            </td>
        );
    });

    const boundRows = [
        <tr key={0} >
            {boundTds[0]}
            {boundTds[1]}
            {boundTds[2]}
        </tr>,
        <tr key={1}>
            {boundTds[3]}
            {boundTds[4]}
            {boundTds[5]}
        </tr>,
        <tr key={2}>
            {boundTds[6]}
            {boundTds[7]}
            {boundTds[8]}
        </tr>,
    ];

    //
    // COMBINER
    //
    function combinerRmv(i) {
        combiner[i] = null;
        return combinerChange(combiner);
    }
    const combinerElement = (
        <table class="vbox-table">
            <tbody>
                <tr>
                    <td onClick={() => combinerRmv(0)}>
                        {combiner[0] !== null ? convertItem(vbox.bound[combiner[0]]) : shapes.vboxColour('gray')}
                    </td>
                    <td onClick={() => combinerRmv(1)}>
                        {combiner[1] !== null ? convertItem(vbox.bound[combiner[1]]) : shapes.vboxColour('gray')}
                    </td>
                    <td onClick={() => combinerRmv(2)}>
                        {convertItem(vbox.bound[combiner[2]])}
                    </td>
                </tr>
            </tbody>
        </table>
    );

    //
    // EVERYTHING
    //

    function reclaimClick(e) {
        e.stopPropagation();
        return setReclaiming(!reclaiming);
    }

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

    const classes = `vbox`;
    const reclaimClass = `vbox-btn reclaim ${reclaiming ? 'reclaiming' : ''}`;

    return (
        <div class={classes}>
            <div class='vbox-box' onClick={() => setReclaiming(false)} onMouseOver={e => hoverInfo(e, 'vbox')} >
                <div class="vbox-hdr">
                    <h3 onTouchStart={e => e.target.scrollIntoView(true)}>VBOX</h3>
                    <div class="bits" onMouseOver={e => hoverInfo(e, 'bits')} >{vbox.bits}b</div>
                </div>
                <button
                    onMouseOver={e => hoverInfo(e, 'reroll')}
                    onClick={() => sendVboxDiscard()}>
                    Reroll
                </button>
                <table class="vbox-table">
                    <tbody>
                        {freeRows}
                    </tbody>
                </table>
            </div>
            <div class='vbox-inventory' onClick={() => setReclaiming(false)} onMouseOver={e => hoverInfo(e, 'inventory')} >
                <h3 onTouchStart={e => e.target.scrollIntoView(true)}>INVENTORY</h3>
                <button
                    class={reclaimClass}
                    onMouseOver={e => hoverInfo(e, 'reclaim')}
                    onClick={reclaimClick}>
                    reclaim
                </button>
                <table class="vbox-table">
                    <tbody>
                        {boundRows}
                    </tbody>
                </table>
            </div>
            <div class="vbox-combiner" onMouseOver={e => hoverInfo(e, 'combiner')} >
                <h3 onTouchStart={e => e.target.scrollIntoView(true)}>I-COMBINATOR</h3>
                <button
                    onMouseOver={e => hoverInfo(e, 'refine')}
                    onClick={() => sendVboxCombine()}>
                    refine
                </button>
                {combinerElement}
            </div>
        </div>
    );
}

module.exports = addState(Vbox);
