import React from 'react'
import type { DisplayOnType } from '.'
import { BREAKPOINT_DESKTOP, DISPLAY_ON_DESKTOP, DISPLAY_ON_PHONE } from '.'
import type { COLLAPSE_ABOVE, COLLAPSE_BELOW } from '../more-menu'
import type { IconProps } from '@planview/pv-icons'

export type ResizeContextType = {
    initialized: boolean
    breakpoint: string
    showLabels: boolean
    showSeparators: boolean
    shouldDisplay: (displayOn: DisplayOnType) => boolean
}

const ResizeContext = React.createContext<ResizeContextType>({
    initialized: false,
    breakpoint: BREAKPOINT_DESKTOP,
    showLabels: true,
    showSeparators: true,
    shouldDisplay: () => true,
})

export default ResizeContext

type WrappingParentContextType = {
    wrappedInToolbarParent: boolean
}

export const WrappingParentContext =
    React.createContext<WrappingParentContextType>({
        wrappedInToolbarParent: false,
    })

type GenericContextType = {
    displayOn: DisplayOnType
    showMoreMenuItem: boolean
}

export const GenericContext = React.createContext<GenericContextType>({
    displayOn: DISPLAY_ON_DESKTOP,
    showMoreMenuItem: false,
})

type MainNavigationContextType = {
    wrappedInNavigation: boolean
}

export const MainNavigationContext =
    React.createContext<MainNavigationContextType>({
        wrappedInNavigation: false,
    })

export const useMainNavigationContext = () =>
    React.useContext(MainNavigationContext)

export type UserMenuConfig = {
    trigger: React.JSX.Element
    children: React.ReactNode
}

type UserMenuContextType = {
    add: (config: UserMenuConfig) => void
    remove: () => void
}

export const UserMenuContext = React.createContext<UserMenuContextType>({
    add: () => {},
    remove: () => {},
})

export const useUserMenu = () => React.useContext(UserMenuContext)

export type MoreMenuChildType = React.ReactElement

type ChildEntry = {
    child: MoreMenuChildType
    id: string
    displayOn: DisplayOnType
}

type CustomMoreMenuState = {
    children: MoreMenuChildType[]
    icon?: React.ReactElement<IconProps>
    collapse: typeof COLLAPSE_ABOVE | typeof COLLAPSE_BELOW
}

type MoreMenuContextType = {
    inMoreMenuSection: boolean
    dispatch: (value: ActionType) => void
    registeredItems: ChildEntry[]
    customMoreMenu: CustomMoreMenuState | null
}

export const MoreMenuContext = React.createContext<MoreMenuContextType>({
    inMoreMenuSection: false,
    dispatch: () => {},
    registeredItems: [],
    customMoreMenu: null,
})

type SectionState = {
    registeredItems: ChildEntry[]
    dropdownOpen: boolean
    customMoreMenu: CustomMoreMenuState | null
}

const InitialState: SectionState = {
    registeredItems: [],
    dropdownOpen: false,
    customMoreMenu: null,
}

type RegisterAction = {
    type: 'REGISTER_CHILD'
    id: string
    child: MoreMenuChildType
    displayOn: DisplayOnType
}

type RegisterMoreMenuAction = {
    type: 'REGISTER_MORE_MENU_CONTENT'
    children: MoreMenuChildType[]
    collapse: typeof COLLAPSE_ABOVE | typeof COLLAPSE_BELOW
    icon?: React.ReactElement<IconProps>
}

type UnRegisterMoreMenuAction = {
    type: 'UNREGISTER_MORE_MENU_CONTENT'
}

type UpdateAction = {
    type: 'UPDATE_CHILD'
    id: string
    child: MoreMenuChildType
    displayOn: DisplayOnType
}

type UnRegisterAction = {
    type: 'UNREGISTER_CHILD'
    id: string
}

type ClearAction = {
    type: 'CLEAR'
}

export type ActionType =
    | RegisterAction
    | ClearAction
    | UnRegisterAction
    | UpdateAction
    | RegisterMoreMenuAction
    | UnRegisterMoreMenuAction

type ProviderProps = {
    children: React.ReactNode
}
const reducer = (state: SectionState, action: ActionType): SectionState => {
    switch (action.type) {
        case 'REGISTER_CHILD': {
            const found = state.registeredItems.find(
                (c: ChildEntry) => c.id === action.id
            )
            if (found) {
                console.warn('child already registered', action.id)
                return state
            }
            const items = [...state.registeredItems]
            items.push({
                id: action.id,
                child: action.child,
                displayOn: action.displayOn,
            })

            return {
                ...state,
                registeredItems: items,
            }
        }
        case 'UPDATE_CHILD':
            return {
                ...state,
                registeredItems: state.registeredItems.map((c) =>
                    c.id === action.id
                        ? {
                              ...c,
                              child: action.child,
                              displayOn: action.displayOn,
                          }
                        : c
                ),
            }
        case 'UNREGISTER_CHILD': {
            const newState = {
                ...state,
                registeredItems: state.registeredItems.filter(
                    (c) => c.id !== action.id
                ),
            }
            return newState
        }
        case 'CLEAR':
            return InitialState
        case 'REGISTER_MORE_MENU_CONTENT':
            return {
                ...state,
                customMoreMenu: action,
            }
        case 'UNREGISTER_MORE_MENU_CONTENT':
            return {
                ...state,
                customMoreMenu: null,
            }
        default:
            return state
    }
}

export const MoreMenuProvider = ({ children }: ProviderProps) => {
    const [state, dispatch] = React.useReducer(reducer, InitialState)

    React.useEffect(() => () => dispatch({ type: 'CLEAR' }), [])

    const context = React.useMemo<MoreMenuContextType>(
        () => ({
            inMoreMenuSection: true,
            dispatch,
            customMoreMenu: state.customMoreMenu,
            registeredItems: state.registeredItems.filter(
                (c) => c.displayOn !== DISPLAY_ON_PHONE
            ),
        }),
        [state, dispatch]
    )
    return (
        <MoreMenuContext.Provider value={context}>
            {children}
        </MoreMenuContext.Provider>
    )
}
