/**
 * TEAM: frontend_infra
 * @flow strict
 */

import * as React from "react";
import {css} from "aphrodite";
import StackingContext from "./StackingContext";
import latitudeColors, {transmissionColors} from "./colors";
import {createThemedStylesheet, type ThemeData} from "./styles";
import ThemeNameContext, {
  TRANSMISSION,
  type Theme,
} from "./context/ThemeNameContext";

type Props = {|
  /** The content that is loading */
  +children?: React.Node,
  /** The loader will take care of the show hide logic. Pass your loading conditional here and wrap your data with this loader. */
  +loaded: boolean,
  /** Whether the loader spans the full width of it's container */
  +isFullWidth?: boolean,
  /** Whether the background of the progress bar is transparent */
  +transparent?: boolean,
  /** Whether the overlay container is position: fixed. Default is position: relative. */
  +fixed?: boolean,
  /** Deprecated! Do not use the overlay prop. */
  +overlay?: boolean,
|};

const LOADER_WIDTH = 50;
const LOADER_BORDER = 4;
const LOADER_ANIMATION_DURATION = 1000;

/**
 * @short A pure CSS progress bar with an indeterminate loading animation.
 * @brandStatus V2
 * @status Stable
 * @category Data Display
 *
 * Indefinite progress bars should be used to indicate that data is loading and will take an unknown amount of time. Progress bars are best used in information-dense UIs like data tables.
 */
export default function ProgressBar({
  children = <span />,
  loaded,
  isFullWidth = true,
  overlay = false,
  transparent = false,
  fixed = false,
}: Props): React.Node {
  const theme = React.useContext(ThemeNameContext);
  const styles = getStyle(theme);
  const {isDeprecatedZIndexEnabled} = React.useContext(StackingContext);

  const [hasAnimationLoaded, setHasAnimationLoaded] = React.useState(false);

  React.useEffect(() => {
    const id = setTimeout(() => {
      setHasAnimationLoaded(true);
    }, LOADER_ANIMATION_DURATION);

    return () => {
      setHasAnimationLoaded(false);
      clearTimeout(id);
    };
  }, [loaded]);

  if (loaded && hasAnimationLoaded) {
    return children;
  }

  return (
    <span
      data-qa-id="ProgressBar"
      className={css(
        fixed ? styles.overlayContainerFixed : styles.overlayContainer,
        isFullWidth && styles.fullWidth,
        isDeprecatedZIndexEnabled && styles.overlayContainerZIndex
      )}
    >
      <div
        className={css(
          styles.base,
          !transparent && styles.background,
          isFullWidth && styles.fullWidth,
          overlay && styles.overlayElement
        )}
      >
        <div
          className={css(
            styles.indeterminateLoading,
            isFullWidth && styles.fullWidthIndeterminateLoading
          )}
        />
      </div>
    </span>
  );
}

const indeterminateLoader = {
  from: {
    left: -(LOADER_WIDTH / 4),
    width: "30%",
  },
  "50%": {
    width: "30%",
  },
  "70%": {
    width: "70%",
  },
  "80%": {
    left: "50%",
  },
  "95%": {
    left: "120%",
  },
  to: {
    left: "100%",
  },
};

const fullWidthIndeterminateLoader = {
  from: {
    left: -(LOADER_WIDTH / 3.5),
    width: "0%",
  },
  "25%": {
    width: "10%",
  },
  "50%": {
    width: "30%",
  },
  "70%": {
    width: "70%",
  },
  "80%": {
    left: "50%",
  },
  "95%": {
    left: "120%",
  },
  to: {
    left: "100%",
  },
};

function getThemeColor(themeName: Theme) {
  if (themeName === TRANSMISSION) {
    return transmissionColors.green30;
  }
  return latitudeColors.grey40;
}

const getStyle = createThemedStylesheet(({themeName}: ThemeData) => {
  const themeColors = getThemeColor(themeName);
  const darkPrimary = latitudeColors.grey60;

  const progress = {
    "100%, 0%": {
      backgroundColor: themeColors,
    },
    "40%": {
      backgroundColor: darkPrimary,
    },
    "66%": {
      backgroundColor: themeColors,
    },
    "80%, 90%": {
      backgroundColor: darkPrimary,
    },
  };

  return {
    base: {
      height: LOADER_BORDER,
      width: LOADER_WIDTH,
      position: "relative",
      overflow: "hidden",
    },
    background: {
      backgroundColor: latitudeColors.grey20,
    },
    indeterminateLoading: {
      display: "block",
      position: "absolute",
      height: LOADER_BORDER,
      backgroundColor: themeColors,
      animationName: [indeterminateLoader, progress],
      animationDuration: `2s, 6s`,
      animationTimingFunction: "linear, ease-in-out",
      animationIterationCount: "infinite, infinite",
    },
    fullWidth: {
      width: "100%",
    },
    fullWidthIndeterminateLoading: {
      animationName: [fullWidthIndeterminateLoader, progress],
    },
    overlayContainer: {
      position: "relative",
    },
    overlayContainerFixed: {
      position: "fixed",
    },
    overlayContainerZIndex: {
      // eslint-disable-next-line flexport/no-zindex-except-specific-values
      zIndex: "100",
    },
    overlayElement: {
      top: 0,
      right: 0,
      bottom: 0,
      left: 0,
      backgroundColor: "rgba(255,255,255,0.78)",
    },
  };
});
