import * as React from "react";

import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";

import { useCellState } from "../MasterCell/utils";
import { FocusableGroup } from "../FocusableGroup";
import { CellWrapper } from "./CellWrapper";
import { styles } from "./styles";

type Props = {
  item: ZappEntry;
  CellRenderer: React.FunctionComponent<any>;
  id: string;
  groupId: string;
  onFocus: Function;
  onBlur?: Function;
  index: number;
  scrollTo: Function;
  preferredFocus?: boolean;
  skipFocusManagerRegistration?: boolean;
  isFocusable?: boolean;
  behavior: Behavior;
  focused?: boolean;
};

const addPrefix = (id: string) => `focusable-cell-wrapper-${id}`;

const wrapperStyles = {
  flex: platformSelect({
    tvos: 1,
    default: undefined,
  }),
};

export function CellWithFocusable(props: Props) {
  const {
    index,
    item,
    CellRenderer,
    id,
    groupId,
    onFocus,
    onBlur = noop,
    scrollTo = noop,
    preferredFocus,
    skipFocusManagerRegistration,
    isFocusable,
    behavior,
    focused,
  } = props;

  const [isFocused, setIsFocused] = React.useState(false);

  const state = useCellState({
    item,
    behavior,
    focused: isFocused || toBooleanWithDefaultFalse(focused),
  });

  const [focusedButtonId, setFocusedButtonId] = React.useState(undefined);

  // for horizontal scrolling
  React.useEffect(() => {
    if (focusedButtonId) {
      scrollTo(index);
    }
  }, [focusedButtonId]);

  const handleToggleFocus = React.useCallback(
    (value) => {
      setFocusedButtonId(value.focusedButtonId);

      if (value.focusable) {
        onFocus(value.focusable, value.mouse);
      }
    },
    [onFocus]
  );

  const onGroupFocus = React.useCallback(() => {
    if (!skipFocusManagerRegistration) {
      setIsFocused(true);
    }
  }, [skipFocusManagerRegistration]);

  const onGroupBlur = React.useCallback(() => {
    if (!skipFocusManagerRegistration) {
      setIsFocused(false);
      onBlur?.();
    }
  }, [skipFocusManagerRegistration]);

  return (
    <FocusableGroup
      id={addPrefix(id)}
      testID={"cell-with-focusable-cell-renderer-focusable-group"}
      groupId={groupId}
      preferredFocus={preferredFocus}
      shouldUsePreferredFocus
      onFocus={onGroupFocus}
      onBlur={onGroupBlur}
      skipFocusManagerRegistration={skipFocusManagerRegistration}
      style={wrapperStyles}
    >
      <CellWrapper style={styles.cellWrapper}>
        <CellRenderer
          testID={"cell-with-focusable-cell-renderer"}
          item={item}
          groupId={addPrefix(id)}
          onToggleFocus={handleToggleFocus}
          state={state}
          prefixId={id}
          focusedButtonId={focusedButtonId}
          preferredFocus={true}
          skipFocusManagerRegistration={skipFocusManagerRegistration}
          isFocusable={isFocusable}
          focused={focused}
        />
      </CellWrapper>
    </FocusableGroup>
  );
}
