import React from 'react';
import {
    Theme as MaterialTheme,
    ThemeOptions as MaterialThemeOptions,
    createTheme as createMaterialTheme,
    ThemeProvider
} from "@mui/material/styles";
import { NoData } from '../services';

type CustomTheme = {
    name: string,
    custom?: {
        infoText: string,
        successText: string,
        warningText: string,
        errorText: string,
    }
}

export type Theme = MaterialTheme & CustomTheme;
export type ThemeOptions = MaterialThemeOptions & CustomTheme;

export namespace Themes {

    /************************************* PROVIDER *************************************/

    interface ContextProps {
        themes: { [name: string]: Theme },
        theme: Theme,
        setTheme: (name: string) => void,
    }

    export const Context = React.createContext<ContextProps>({
        themes: {},
        theme: NoData,
        setTheme: () => { },
    });

    interface ProviderProps {
        defaultTheme?: string,
        themes: ThemesMap,
        children?: React.ReactNode | React.ReactNode[] | any,
    }

    export const Provider: React.FC<ProviderProps> = ({ defaultTheme, themes, children }) => {
        const currentDefaultTheme = defaultTheme && themes
            ? Object.values(themes).find(x => x.name === defaultTheme)
            : { name: 'light' };
        const [themeName, setThemeName] = React.useState(
            (localStorage && localStorage.getItem('app-theme') && localStorage.getItem('app-theme') !== 'null')
                ? localStorage.getItem('app-theme')
                : (currentDefaultTheme?.name ?? '')
        );

        const getTheme = (name: string) => {
            return name && themes
                ? Object.values(themes).find(x => x.name === name)
                : Object.values(themes).length > 0
                    ? Object.values(themes)[0]
                    : null;
        }
        const handleThemeNameChange = (name: string) => {
            const theme = getTheme(name);

            if (localStorage) {
                localStorage.setItem('app-theme', theme?.name ?? '');
            }
            setThemeName(theme?.name ?? 'light');
        }
        const theme = getTheme(themeName);

        return (
            <Context.Provider value={{
                themes,
                theme,
                setTheme: handleThemeNameChange,
            }}>
                <ThemeProvider theme={theme}>
                    {children}
                </ThemeProvider>
            </Context.Provider >
        );
    }

    /************************************* THEMES *************************************/

    export interface ThemesMap {
        [name: string]: any,
    }

}
export default Themes;

export function createTheme(options?: ThemeOptions | undefined, ...args: object[]): Theme {
    const innerOptions = { ...options, custom: undefined as any }

    const result = createMaterialTheme(innerOptions, ...args) as Theme;
    result.name = options?.name ?? '';
    result.custom = options?.custom;

    return result;
}