import { useCallback, useEffect, useRef, useState } from 'react'
import './App.css'
import { useUserAPI } from '../providers/pond/userAPI'
import { useAuth0 } from '@auth0/auth0-react'
import { or } from '../utils/types'
import LoadingScreen from './LoadingScreen'
import NavigationContainer from '../navigation/NavigationContainer'
import { GlobalState, GlobalStateAction, StateProvider } from '../providers/StateContainer'
import { User } from '../models/user'
import { Team } from '../models/team'
import { makeStyles } from '@mui/styles'
import { CssBaseline, Theme } from '@mui/material'
import { AppThemeProvider } from 'theme/AppThemeProvider'
import HTTPProvider from 'providers/http'
// import FirmwareLoader from './FirmwareLoader'

const reducer = (state: GlobalState, action: GlobalStateAction): GlobalState => {
  return {
    ...state,
    [action.key]: action.value
  };
};

const useStyles = makeStyles((theme: Theme) => ({
  appContent: {
    paddingTop: 56,
    paddingBottom: 56,
    paddingLeft: "0px",
    [theme.breakpoints.up("sm")]: {
      paddingTop: 64,
      paddingBottom: 0,
    },
    [theme.breakpoints.up("md")]: {
      paddingLeft: theme.spacing(9)
    },
  },
  container: {
    backgroundColor: theme.palette.background.default,
  },
  helloMessage: {
    marginTop: theme.spacing(2),
  },
}))

const globalDefault = {
  user: User.create(),
  team: Team.create(),
  as: "",
  showErrors: false,
  userTeamPermissions: [],
  backgroundTasksComplete: false,
  firmware: new Map(),
}

interface Props {
  token: string;
}

export default function UserWrapper(props: Props) {
  const { token } = props;
  const [loading, setLoading] = useState(false)
  const userAPI = useUserAPI();
  const classes = useStyles();
  const useAuth = useAuth0();
  const hasFetched = useRef(false);
  const [global, setGlobal] = useState<undefined | GlobalState>(undefined)

  const user_id = or(useAuth.user?.sub, "")

  const loadUser = useCallback(() => {
    if (!userAPI.getUserWithTeam) return;
    if (hasFetched.current) return;
    setLoading(true)
    userAPI.getUserWithTeam(user_id).then(resp => {
      setGlobal({
        user: resp.data.user ? User.create(resp.data.user) : User.create(),
        team: resp.data.team ? Team.create(resp.data.team) : Team.create(),
        as: resp.data.user?.settings?.useTeam === true ? resp.data.user.settings.defaultTeam : "",
        showErrors: false,
        userTeamPermissions: [],
        backgroundTasksComplete: false,
        firmware: new Map()
      })
    }).catch(() => {
      userAPI.getUser(user_id).then(user => {
        setGlobal({
          user: user ? user : User.create(),
          team: globalDefault.team,
          as: "",
          showErrors: false,
          userTeamPermissions: [],
          backgroundTasksComplete: false,
          firmware: new Map()
        })
      }).catch(() => {
        setGlobal(globalDefault)
      })
      
    })
    .finally(() => {
      setLoading(false)
      hasFetched.current = true;
    })
  }, [setGlobal])
  
  useEffect(() => {
    if (loading) return;
    loadUser()
  }, [loading])
  
  if (loading || !global) return (
    <LoadingScreen />
  )

  return (
    <StateProvider state={global} reducer={reducer}>
      <AppThemeProvider >
        <CssBaseline/>
        <main className={classes.appContent}>
          <HTTPProvider token={token}>
            <NavigationContainer />
          </HTTPProvider>
        </main>
      </AppThemeProvider>
    </StateProvider>
  )
}