import * as React from "react";

import { BaseFocusable } from "../BaseFocusable";
import { FocusableGroupContextProvider } from "../../Contexts/FocusableGroupContext";
import { withFocusableContext } from "../../Contexts/FocusableGroupContext/withFocusableContext";

type Props = {
  testID?: string;
  shouldUsePreferredFocus?: boolean;
  id: string;
  node?: Record<any, any>;
  children: any;
  preferredFocus?: boolean;
  isWithMemory?: boolean;
  style?: Record<any, any>;
  prioritiseFocusOn?: number;
  groupId?: string;
  hasTVPreferredFocus?: boolean;
  resetFocusToInitialValue?: boolean;
  onFocus?: () => void;
  onBlur?: () => void;
  onWillUpdateFocus?: (event?: any) => void;
  willReceiveFocus?: (event?: any) => void;
  onDidUpdateFocus?: (event?: any) => void;
  hasLostFocus?: any;
  nextFocusUp?: any;
  nextFocusDown?: any;
  nextFocusLeft?: any;
  nextFocusRight?: any;
  onLayout?: any;
  excludeFromFocusSearching?: boolean;
};

class FocusableGroup extends BaseFocusable<Props> {
  constructor(props) {
    super(props);
    this.isGroup = true;
    this.shouldUsePreferredFocus = this.shouldUsePreferredFocus.bind(this);
    this.isPreferredFocus = this.isPreferredFocus.bind(this);
    this.isWithMemory = this.isWithMemory.bind(this);
  }

  getId() {
    const { id } = this.props;

    return id;
  }

  /**
   * tells whether the group should give focus to a preferred item when it gains focus from another
   * group
   * @returns {boolean}
   */
  shouldUsePreferredFocus() {
    return this.props.shouldUsePreferredFocus || false;
  }

  /**
   * indicates whether the underlying component should claim preferred focus
   * when navigating into the group of this item
   * @returns {boolean}
   */
  isPreferredFocus() {
    return this.props.preferredFocus || false;
  }

  /**
   * indicates whether the Group should remember last focused item
   * or focus on preferredFocus
   * @returns {boolean}
   */
  isWithMemory() {
    return this.props.isWithMemory ?? true;
  }

  render() {
    const { children, id, style } = this.props;
    const focusableId = `focusable-group-${id}`;

    return (
      <div
        id={focusableId}
        data-testid={focusableId}
        style={style}
        ref={this.ref}
      >
        <FocusableGroupContextProvider id={id}>
          {children}
        </FocusableGroupContextProvider>
      </div>
    );
  }
}

const FocusableGroupWithFocusableContext = withFocusableContext(FocusableGroup);

export { FocusableGroupWithFocusableContext as FocusableGroup };
