import React, { useReducer, useMemo, useContext } from "react";
import PropTypes from "prop-types";
import { ThemeProvider as MuiThemeProvider } from "@mui/material/styles";
import { localStorage } from "@flare/js-utils";
import { getThemes } from "../units/themes";

const ApplicationThemeContext = React.createContext();
const LOCAL_STORAGE_COLOR_SCHEME_KEY = "network-resurrector-color-scheme";

const COLOR_SCHEME = {
  LIGHT: "light",
  DARK: "dark"
};

const colorScheme = localStorage.getItem(LOCAL_STORAGE_COLOR_SCHEME_KEY);
const prefersDarkMode = window.matchMedia("(prefers-color-scheme: dark)").matches;

const initialState = {
  scheme: colorScheme ?? (prefersDarkMode ? COLOR_SCHEME.DARK : COLOR_SCHEME.LIGHT)
};

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case "onColorSchemeChanged": {
      return {
        ...state,
        scheme: action.scheme
      };
    }
    default: {
      return state;
    }
  }
};

const dispatchActions = dispatch => ({
  onColorSchemeChanged: scheme => {
    dispatch({ type: "onColorSchemeChanged", scheme });
    localStorage.setItem(LOCAL_STORAGE_COLOR_SCHEME_KEY, scheme);
  }
});

const useApplicationTheme = () => {
  const { state, actions } = useContext(ApplicationThemeContext);
  const { onColorSchemeChanged } = actions;

  const { scheme } = state;
  const onDarkModeChanged = active => onColorSchemeChanged(active ? COLOR_SCHEME.DARK : COLOR_SCHEME.LIGHT);

  return { isDark: scheme === COLOR_SCHEME.DARK, onDarkModeChanged };
};

const ThemeProvider = ({ children }) => {
  const [state, dispatch] = useReducer(reducer, initialState);
  const actions = useMemo(() => dispatchActions(dispatch), [dispatch]);
  const themes = useMemo(() => getThemes(state.scheme === COLOR_SCHEME.DARK), [state.scheme]);

  return (
    <ApplicationThemeContext.Provider
      value={{
        state,
        actions
      }}
    >
      <MuiThemeProvider theme={themes.default}>{children}</MuiThemeProvider>
    </ApplicationThemeContext.Provider>
  );
};

ThemeProvider.propTypes = {
  children: PropTypes.node.isRequired
};

export { ThemeProvider, ApplicationThemeContext, useApplicationTheme };
export default ThemeProvider;
