import color from 'color';
import * as React from 'react';
import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native';
import { withTheme } from '../../core/theming';
import Icon, { IconSource } from '../Icon';
import TouchableRipple from '../TouchableRipple/TouchableRipple';
import Text from '../Typography/Text';

type Props = React.ComponentPropsWithRef<typeof View> & {
  /**
   * The label text of the item.
   */
  label: React.ReactNode;
  /**
   * Icon to display for the `DrawerItem`.
   */
  icon?: IconSource;
  /**
   * Whether to highlight the drawer item as active.
   */
  active?: boolean;
  /**
   * Number of lines to display for text, defaults to 1.
   */
  numberOfLines?: number;
  /**
   * Function to execute on press.
   */
  onPress?: () => void;
  /**
   * Accessibility label for the button. This is read by the screen reader when the user taps the button.
   */
  accessibilityLabel?: string;
  /**
   * Callback which returns a React element to display on the right side. For instance a Badge.
   */
  right?: (props: { color: string }) => React.ReactNode;
  style?: StyleProp<ViewStyle>;
  /**
   * @optional
   */
  theme: ReactNativePaper.Theme;
};

/**
 * A component used to show an action item with an icon and a label in a navigation drawer.
 *
 * <div class="screenshots">
 *   <figure>
 *     <img class="medium" src="screenshots/drawer-item.png" />
 *   </figure>
 * </div>
 *
 * ## Usage
 * ```js
 * import * as React from 'react';
 * import { Drawer } from 'react-native-paper';
 *
 * const MyComponent = () => (
 *    <Drawer.Item
 *      style={{ backgroundColor: '#64ffda' }}
 *      icon="star"
 *      label="First Item"
 *    />
 * );
 *
 * export default MyComponent;
 * ```
 */
const DrawerItem = React.forwardRef(
  (
    {
      icon,
      label,
      active,
      theme,
      style,
      onPress,
      numberOfLines,
      right,
      accessibilityRole,
      accessibilityLabel,
      importantForAccessibility,
      accessibilityElementsHidden,
      ...rest
    }: Props,
    ref: React.ForwardedRef<View>
  ) => {
    const { colors, roundness } = theme;
    const backgroundColor = active
      ? color(colors.primary).alpha(0.12).rgb().string()
      : 'transparent';
    const contentColor = active
      ? colors.primary
      : color(colors.text).alpha(0.68).rgb().string();
    const font = theme.fonts.medium;
    const labelMargin = icon ? 32 : 0;
    const numLines = typeof numberOfLines === 'undefined' ? 1 : numberOfLines;
    let labelElement = label;
    if (typeof label === 'string') {
      labelElement = (
        <Text
          numberOfLines={numLines}
          selectable={false}
          style={[
            styles.label,
            {
              color: contentColor,
              ...font,
              marginLeft: labelMargin,
            },
          ]}
        >
          {label}
        </Text>
      );
    }

    return (
      <View {...rest}>
        <TouchableRipple
          borderless
          delayPressIn={0}
          onPress={onPress}
          style={[
            styles.container,
            { backgroundColor, borderRadius: roundness },
            style,
          ]}
          ref={ref as any}
          // @ts-expect-error We keep old a11y props for backwards compat with old RN versions
          accessibilityTraits={active ? ['button', 'selected'] : 'button'}
          accessibilityComponentType="button"
          accessibilityRole={accessibilityRole ?? 'button'}
          accessibilityState={{ selected: active }}
          accessibilityLabel={accessibilityLabel}
          accessibilityElementsHidden={accessibilityElementsHidden}
        >
          <View
            style={styles.wrapper}
            importantForAccessibility={importantForAccessibility}
          >
            <View style={styles.content}>
              {icon ? (
                <Icon source={icon} size={24} color={contentColor} />
              ) : null}
              {labelElement}
            </View>
            {right?.({ color: contentColor })}
          </View>
        </TouchableRipple>
      </View>
    );
  }
);

DrawerItem.displayName = 'Drawer.Item';

const styles = StyleSheet.create({
  container: {
    marginHorizontal: 10,
    marginVertical: 4,
  },
  wrapper: {
    flexDirection: 'row',
    alignItems: 'center',
    padding: 8,
  },
  content: {
    flex: 1,
    flexDirection: 'row',
    alignItems: 'center',
  },
  label: {
    marginRight: 32,
  },
});

export default withTheme(DrawerItem);
