import React, { memo } from "react";

import { Box, Stack, Typography } from "@mui/material";
import CircularProgress from "@mui/material/CircularProgress";
import Fade from "@mui/material/Fade";
import { Theme, useTheme } from "@mui/material/styles";
import { alpha } from "@mui/system";

import Logo from "../components/Logo";
import { LogoType } from "../types";
import { ss } from "../util/select_styles";

const styles = (theme: Theme) =>
  ({
    root: {
      position: "fixed",
      top: 0,
      left: 0,
      width: "100%",
      height: "100%",
    },
    backdrop: {
      position: "absolute",
      zIndex: 2000,
      backgroundColor: alpha(theme.palette.background.default, 0.666),
    },
    backdropPrimary: {
      backgroundColor: alpha(theme.palette.primary.main, 0.666),
    },
    backdropSecondary: {
      backgroundColor: alpha(theme.palette.secondary.main, 0.666),
    },
    backdropPaper: {
      backgroundColor: alpha(theme.palette.background.paper, 0.666),
    },
    spinner: {
      color: theme.palette.primary.main,
    },
    spinnerContrast: {
      color: theme.palette.primary.contrastText,
    },
    logo: {
      position: "absolute",
      margin: 0,
      marginTop: theme.spacing(-36),
    },
  }) as const;

export interface LoadingScreenBaseProps {
  color?: string;
  label?: string;
  loading?: boolean;
  logo?: LogoType;
}

export interface LoadingScreenInnerProps extends LoadingScreenBaseProps {
  classes: ReturnType<typeof styles>;
  backdrop: boolean;
}

const LoadingScreenInner: React.FC<LoadingScreenInnerProps> = ({
  backdrop,
  classes,
  color,
  label,
  loading,
  logo,
}) => (
  <Stack
    alignItems="center"
    direction="column"
    gap={2}
    justifyContent="center"
    sx={ss(
      classes.root,
      [classes.backdrop, backdrop],
      [classes.backdropPrimary, backdrop && color === "primary"],
      [classes.backdropSecondary, backdrop && color === "secondary"],
      [classes.backdropPaper, backdrop && color === "paper"],
    )}
  >
    <Box sx={classes.logo}>{logo != null && <Logo src={logo} />}</Box>
    {loading && <CircularProgress sx={ss(classes.spinner, [classes.spinnerContrast, !color])} />}

    {label != null && (
      <Typography color="grey.600" variant="body2">
        {label}
      </Typography>
    )}
  </Stack>
);

export interface LoadingScreenProps extends LoadingScreenBaseProps {
  backdrop?: boolean;
  classes?: ReturnType<typeof styles>;
}

export const LoadingScreen: React.FC<LoadingScreenProps> = ({
  backdrop = false,
  classes = styles(useTheme()),
  color,
  label,
  loading = true,
  logo,
}) =>
  backdrop ? (
    <Fade in={loading} timeout={{ enter: 750, exit: 250 }}>
      <div>
        <LoadingScreenInner
          backdrop={backdrop}
          classes={classes}
          color={color}
          label={label}
          loading={loading}
          logo={logo}
        />
      </div>
    </Fade>
  ) : (
    <LoadingScreenInner
      backdrop={backdrop}
      classes={classes}
      color={color}
      label={label}
      loading={loading}
      logo={logo}
    />
  );

export default memo(LoadingScreen);
