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

import * as React from "react";
import {StyleSheet, css} from "aphrodite";
import latitudeColors from "../colors";
import {SelectionListContext} from "./SelectionList";

/** Internal Latitude component used for SelectionList which is used for components such as DropdownList */

type Props = {|
  /** The content displayed for the option, if not defined, uses the value instead */
  +children?: React.Node,
  /** The value for the option */
  +value: string,
  /** whether the option is disabled */
  +disabled?: boolean,
|};

/**
 * @category Data Entry
 * @short A singular option used by SelectionList
 * @brandStatus V2
 * @status In Review
 */
export default function SelectionListOption({
  value,
  children,
  disabled = false,
}: Props): React.Element<"div"> {
  const context = React.useContext(SelectionListContext);
  const optionElementRef = React.useRef();
  const optionRepresentation = React.useRef<{|
    value: string,
    +elementRef: {|current: ?HTMLElement|},
  |}>({
    value,
    elementRef: optionElementRef,
  });
  const content = children === undefined ? value : children;
  const isSelected = context.selected != null && context.selected === value;
  // We use `isReadyForTransition` to wait to apply CSS transition style  so we don't show transitions right when the component appears
  const isReadyForTransition = React.useRef(false);

  React.useEffect(() => {
    isReadyForTransition.current = true;
  }, []);

  React.useEffect(() => {
    if (optionRepresentation.current)
      optionRepresentation.current.value = value;
  }, [value]);

  React.useEffect(() => {
    const representation = optionRepresentation.current;

    // If option is disabled, do not track it and treat as non-existent
    if (!disabled) context.addOption(representation);

    return () => {
      context.removeOption(representation);
    };
  }, [context, disabled]);

  return (
    <div
      role="button"
      tabIndex={-1}
      className={css(styles.option, disabled && styles.optionDisabled)}
      onMouseDown={() => {
        if (!disabled && !isSelected) {
          context.select(value);
        }
      }}
      onMouseEnter={() => {
        if (!disabled) context.highlightOption(optionRepresentation.current);
      }}
      data-qa-id={`option-${value}`}
      ref={optionElementRef}
    >
      <div className={css(styles.optionBackgroundWrapper)}>
        <div
          className={css(
            styles.optionBackground,
            isSelected && styles.optionBackgroundActive,
            isReadyForTransition.current && styles.optionBackgroundTransition
          )}
        />
      </div>
      <div className={css(styles.optionContent)}>
        {typeof content === "string" ? (
          <div className={css(styles.optionText)}>{content}</div>
        ) : (
          children
        )}
      </div>
    </div>
  );
}

const styles = StyleSheet.create({
  option: {
    cursor: "pointer",
    position: "relative",
    outline: "none",
  },
  optionContent: {
    position: "relative",
  },
  optionText: {
    lineHeight: "32px",
    padding: "0 12px",
    whiteSpace: "nowrap",
    textAlign: "start",
    color: latitudeColors.grey60,
  },
  optionBackgroundWrapper: {
    width: "100%",
    height: "100%",
    position: "absolute",
    top: 0,
    left: 0,
    overflow: "hidden",
  },
  optionBackground: {
    background: latitudeColors.grey30,
    transform: "translateX(-100%)",
    width: "100%",
    height: "100%",
    pointerEvents: "none",
    position: "absolute",
    top: 0,
    left: 0,
  },
  optionBackgroundActive: {
    transform: "translateX(0%)",
  },
  optionBackgroundTransition: {
    // easing is ease-out cubic
    transition: `transform 350ms cubic-bezier(0.215, 0.610, 0.355, 1.000)`,
  },
  optionDisabled: {
    color: latitudeColors.grey40,
    ":hover": {
      background: latitudeColors.white,
    },
    cursor: "default",
  },
});
