import {createContext, useContext, useEffect, useReducer} from "react";
import {useWS} from "./useWS.jsx";

const CardContext = createContext({comb: {}, team: []});
const CardDispatchContext = createContext(() => {
});

function compareCards(a, b) {
    for (const keys of Object.keys(a)) {
        if (a[keys] !== b[keys]) {
            return false;
        }
    }
    return true;
}

const CARD_TYPE_ORDER = [
    'BLUE',
    'YELLOW',
    'RED',
    'BLACK'
]

export function compareCardOrder(a, b) {
    if (!a || !b) return 0;
    return CARD_TYPE_ORDER.indexOf(a.type) - CARD_TYPE_ORDER.indexOf(b.type);
}

function reducer(state, action) {
    switch (action.type) {
        case 'SET_CARD':
            if (state.comb[action.payload.id] === undefined || !compareCards(action.payload, state.comb[action.payload.id])) {
                return {
                    comb: {
                        ...state.comb,
                        [action.payload.id]: action.payload
                    },
                    team: state.team
                }
            }
            return state
        case 'SET_ALL':
            if (action.payload.some(e => state.comb[e.id] === undefined || !compareCards(e, state.comb[e.id]))) {
                const newCombs = {};
                for (const o of action.payload) {
                    newCombs[o.id] = o;
                }

                return {
                    comb: {
                        ...state.comb,
                        ...newCombs
                    },
                    team: state.team
                }
            }
            return state
        case 'REMOVE_CARDS':
            const newState = {...state}
            for (const id of action.payload)
                delete newState.comb[id]
            return newState
        case 'SET_TEAM_CARD':
            return {
                comb: state.comb,
                team: [...state.team.filter(e => e.teamName !== action.payload.teamName || e.teamUuid !== action.payload.teamUuid || e.type !== action.payload.type),
                    action.payload]
            }
        case 'REMOVE_TEAM_CARD':
            return {
                comb: state.comb,
                team: [...state.team.filter(e => e.teamName !== action.payload.teamName || e.teamUuid !== action.payload.teamUuid || e.type !== action.payload.type)]
            }

        default:
            return state
    }
}

function WSListener({dispatch}) {
    const {dispatch: dispatchWS} = useWS()

    useEffect(() => {
        const sendCards = ({data}) => {
            dispatch({type: 'SET_ALL', payload: data});
        }
        const rmCards = ({data}) => {
            dispatch({type: 'REMOVE_CARDS', payload: data});
        }
        const sendTeamCard = ({data}) => {
            dispatch({type: 'SET_ALL', payload: data.cards});
            dispatch({
                type: 'SET_TEAM_CARD',
                payload: {teamName: data.teamName, teamUuid: data.teamUuid, type: data.type, reason: data.reason, date: data.date}
            });
        }
        const rmTeamCard = ({data}) => {
            dispatch({
                type: 'REMOVE_TEAM_CARD',
                payload: {teamName: data.teamName, teamUuid: data.teamUuid, type: data.type, reason: data.reason, date: data.date}
            });
        }

        dispatchWS({type: 'addListener', payload: {callback: sendCards, code: 'sendCards'}})
        dispatchWS({type: 'addListener', payload: {callback: rmCards, code: 'rmCards'}})
        dispatchWS({type: 'addListener', payload: {callback: sendTeamCard, code: 'sendTeamCard'}})
        dispatchWS({type: 'addListener', payload: {callback: rmTeamCard, code: 'rmTeamCard'}})
        return () => {
            dispatchWS({type: 'removeListener', payload: sendCards})
            dispatchWS({type: 'removeListener', payload: rmCards})
            dispatchWS({type: 'removeListener', payload: sendTeamCard})
            dispatchWS({type: 'removeListener', payload: rmTeamCard})
        }
    }, []);

    return <></>
}

export function CardsProvider({children}) {
    const [cards, dispatch] = useReducer(reducer, {comb: {}, team: []})

    return <CardContext.Provider value={cards}>
        <CardDispatchContext.Provider value={dispatch}>
            {children}
            <WSListener dispatch={dispatch}/>
        </CardDispatchContext.Provider>
    </CardContext.Provider>
}

export function useCards() {
    const cards = useContext(CardContext);
    return {
        cards_t: cards.team,
        cards_v: Object.values(cards.comb),
        ...useCardsStatic(Object.values(cards.comb))
    }
}

export function useCardsStatic(cards_v) {
    return {
        getCardInMatch: (match) => {
            return cards_v.filter(card => (card.comb === match.c1 || card.comb === match.c2) && card.match === match.id);
        },
        getHeightCardForCombInMatch: (combId, match) => {
            return cards_v.filter(card => card.comb === combId && (card.category === match.categorie || (card.match !== match.id && card.type !== "BLUE"))).sort(compareCardOrder).pop()
        }
    }
}

export function useCardsDispatch() {
    return useContext(CardDispatchContext);
}

export function hasEffectCard(card, matchId, categoryId) {
    switch (card.type) {
        case 'BLUE':
            return false;
        case 'YELLOW':
            return card.match === matchId;
        case 'RED':
            return card.match === matchId || card.category === categoryId;
        case 'BLACK':
            return true;
        default:
            return false;
    }
}
