import React from "react";
import {
  AccessibilityRole,
  ImageBackground,
  ImageSourcePropType,
  StyleProp,
  TextStyle,
  ViewStyle,
} from "react-native";

import theme from "mazlo-theme";

import { Text } from "../Text";
import BaseButton from "./BaseButton";
import styles from "./styles";

export type ButtonPropsType = {
  accessibilityLabel?: string;
  accessibilityRole?: AccessibilityRole;
  backgroundImage?: ImageSourcePropType;
  children?: React.ReactNode;
  disabled?: boolean;
  href?: string;
  onPress?: (e: any) => void;
  onPressIn?: (e: any) => void;
  style?: StyleProp<ViewStyle>;
  textStyle?: StyleProp<TextStyle>;
  backgroundStyle?: StyleProp<ViewStyle>;
  size?: "sm" | "md";
  variant?: keyof typeof theme.variants.buttons;
  title?: string;
  pill?: boolean;
  loading?: boolean;
};

const Button = React.forwardRef<any, ButtonPropsType>(
  (
    {
      accessibilityLabel,
      accessibilityRole = "button",
      backgroundImage,
      backgroundStyle,
      children,
      disabled,
      style,
      textStyle,
      pill,
      variant,
      loading,
      title,
      ...props
    }: ButtonPropsType,
    ref
  ) => {
    const isDisabled = disabled || loading;
    const backgroundView = backgroundImage ? (
      <ImageBackground
        source={backgroundImage}
        style={[styles.backgroundImage, backgroundStyle]}
      />
    ) : null;

    const childComponents = children ? (
      React.Children.map(children, (child) => {
        if (child === null || typeof child !== "object") return child;

        // @ts-ignore
        const { type: { displayName } = {}, props: childProps } = child;

        if (displayName === "Text") {
          return React.cloneElement(child as any, {
            style: [
              styles.text,
              variant && theme.variants.text[variant],
              textStyle,
            ],
            ...childProps,
          });
        }

        return child;
      })
    ) : title ? (
      <Text
        selectable={false}
        style={[
          styles.text,
          variant && theme.variants.text[variant],
          textStyle,
        ]}
      >
        {title}
      </Text>
    ) : null;

    const buttonStyles = [
      styles.container,
      variant && theme.variants.buttons[variant],
      pill && styles.pill,
      isDisabled && styles.disabled,
      style,
    ];

    return (
      <BaseButton
        accessibilityLabel={accessibilityLabel}
        accessibilityRole={accessibilityRole}
        style={buttonStyles}
        disabled={isDisabled}
        {...props}
      >
        {backgroundView}
        {loading ? (
          <Text
            selectable={false}
            style={[
              styles.text,
              variant && theme.variants.text[variant],
              textStyle,
            ]}
          >
            Loading...
          </Text>
        ) : (
          childComponents
        )}
      </BaseButton>
    );
  }
);

export default Button;
