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

const CombsContext = createContext({});
const CombsDispatchContext = createContext(() => {
});

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

function reducer(state, action) {
    switch (action.type) {
        case 'SET_COMB':
            const comb = (action.payload.source === "register") ? action.payload.data : ({
                id: action.payload.data.id,
                fname: action.payload.data.fname,
                lname: action.payload.data.lname,
                genre: action.payload.data.genre,
                country: action.payload.data.country,
                teamMembers: action.payload.data.teamMembers,
            })
            if (state[comb.id] === undefined || !compareCombs(comb, state[comb.id])) {
                //console.debug("Updating comb", comb);
                return {
                    ...state,
                    [comb.id]: {...state[comb.id], ...comb}
                }
            }
            return state
        case 'SET_ALL':
            // By default, we only update some fields to avoid overwriting with incomplete data
            const combs = (action.payload.source === "register") ? action.payload.data : action.payload.data.map(e => {
                return {
                    id: e.id,
                    fname: e.fname,
                    lname: e.lname,
                    genre: e.genre,
                    country: e.country,
                    teamMembers: e.teamMembers,
                }
            });

            if (combs.some(e => state[e.id] === undefined || !compareCombs(e, state[e.id]))) {
                const newCombs = {};
                for (const o of combs) {
                    newCombs[o.id] = {
                        ...state[o.id],
                        ...o
                    };
                }
                //console.debug("Updating combs", newCombs);

                return {
                    ...state,
                    ...newCombs
                }
            }
            return state
        case 'REMOVE_COMB':
            const newState = {...state}
            delete newState[action.payload]
            return newState
        default:
            return state
    }
}

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

    useEffect(() => {
        const sendRegister = ({data}) => {
            dispatch({type: 'SET_COMB', payload: {source: "register", data: data}});
        }

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

    return <></>
}

export function CombsProvider({children}) {
    const [combs, dispatch] = useReducer(reducer, {})

    return <CombsContext.Provider value={combs}>
        <CombsDispatchContext.Provider value={dispatch}>
            {children}
            <WSListener dispatch={dispatch}/>
        </CombsDispatchContext.Provider>
    </CombsContext.Provider>
}

export function useCombs() {
    const combs = useContext(CombsContext);
    const getComb = (id, defaultValue = null) => {
        return combs[id] !== undefined ? combs[id] : defaultValue;
    }
    return {getComb, combs};
}

export function useCombsDispatch() {
    return useContext(CombsDispatchContext);
}

export function CombName({combId}) {
    const {getComb} = useCombs();
    const comb = getComb(combId, null);
    if (comb) {
        if (comb.lname === "__team")
            return <>{comb.fname}</>
        return <>{comb.fname} {comb.lname}</>
    } else {
        return <>[Comb #{combId}]</>
    }
}
