import * as React from "react";
import {
  ActivityIndicator,
  View,
  StyleSheet,
  TouchableHighlightProps,
  StyleProp,
  ViewStyle,
  TextStyle,
} from "react-native";
import color from "color";
import Config from "./Config";
import Text from "./Text";
import Touchable from "./Touchable";
import Elevation from "./Elevation";
import { withTheme } from "../theming";

import type { Theme } from "../styles/DefaultTheme";
import type { IconSlot } from "../interfaces/Icon";

/**
 * A floating action button represents the primary action in an application.
 *
 * <div class="screenshots">
 *   <img src="screenshots/fab-1.png" />
 *   <img src="screenshots/fab-2.png" />
 * </div>
 *
 * ## Usage
 * ```js
 * import * as React from 'react';
 * import { StyleSheet } from 'react-native';
 * import { FAB } from '@draftbit/ui';
 *
 * const MyComponent = () => (
 *   <FAB
 *     style={styles.fab}
 *     type="outline"
 *     icon="add"
 *     onPress={() => console.log('Pressed')}
 *   />
 * );
 *
 * const styles = StyleSheet.create({
 *   fab: {
 *     position: 'absolute',
 *     margin: 16,
 *     right: 0,
 *     bottom: 0,
 *   },
 * })
 *
 * export default MyComponent;
 * ```
 */

type Props = {
  disabled?: boolean;
  type?: "solid" | "extended" | "outline" | "fixed" | "standard";
  loading?: boolean;
  icon?: string;
  color?: string;
  label?: string;
  onPress: () => void;
  elevation?: number;
  theme: Theme;
  style?: StyleProp<ViewStyle>;
} & TouchableHighlightProps &
  IconSlot;

const FAB: React.FC<Props> = ({
  Icon,
  icon,
  disabled = false,
  type = "solid",
  loading = false,
  color: colorOverride,
  label,
  onPress,
  elevation = 0,
  style,
  theme: { colors, disabledOpacity, roundness, typography },
  ...rest
}) => {
  let backgroundColor, borderColor, textColor, borderWidth;
  const buttonColor = colorOverride || colors.primary;

  if (type === "standard" || type === "extended" || type === "fixed") {
    backgroundColor = buttonColor;

    if (disabled) {
      textColor = color(colors.surface).alpha(disabledOpacity).rgb().string();
    } else {
      textColor = colors.surface;
    }
  } else {
    backgroundColor = "transparent";

    if (disabled) {
      textColor = color(buttonColor).alpha(disabledOpacity).rgb().string();
    } else {
      textColor = buttonColor;
    }
  }

  if (type === "outline") {
    if (disabled) {
      borderColor = color(buttonColor).alpha(disabledOpacity).rgb().string();
    } else {
      borderColor = buttonColor;
    }
    borderWidth = StyleSheet.hairlineWidth;
  } else {
    borderColor = "transparent";
    borderWidth = 0;
  }

  const buttonStyle: StyleProp<ViewStyle> = {
    backgroundColor,
    borderColor,
    borderWidth,
    borderRadius: roundness,
    alignItems: "center",
    justifyContent: "center",
  };

  const buttonStyles: StyleProp<ViewStyle>[] = [styles.button, buttonStyle];

  const contentStyle: StyleProp<ViewStyle>[] = [styles.content];

  const textStyle: StyleProp<TextStyle> = {
    textAlign: "center",
    color: textColor,
  };

  const iconStyle: StyleProp<ViewStyle>[] = [
    styles.icon,
    {
      width: Config.buttonIconSize,
    },
  ];

  if (type === "standard" || type === "outline") {
    buttonStyle.width = Config.FABSize;
    buttonStyle.height = Config.FABSize;
    buttonStyle.borderRadius = Config.FABBorderRadius;

    contentStyle.push({
      width: Config.FABSize,
      height: Config.FABSize,
    });
  }

  if (type === "extended" || type === "fixed") {
    iconStyle.push({
      marginLeft: 16,
      marginRight: -8,
    });

    textStyle.margin = 16;
  }

  if (type === "fixed") {
    buttonStyles.push({
      height: Config.FABFixedHeight,
      alignSelf: "stretch",
    });
  }

  return (
    <Elevation style={[{ elevation }, style]}>
      <Touchable
        {...rest}
        onPress={onPress}
        accessibilityState={{ disabled }}
        accessibilityRole="button"
        disabled={disabled || loading}
        style={buttonStyles}
      >
        <View style={styles.content}>
          {icon && loading !== true ? (
            <View style={iconStyle}>
              <Icon
                name={icon}
                size={Config.buttonIconSize}
                color={textColor}
              />
            </View>
          ) : null}
          {loading ? (
            <ActivityIndicator
              size="small"
              color={textColor}
              style={iconStyle}
            />
          ) : null}
          {label ? (
            <Text numberOfLines={1} style={[textStyle, typography.button]}>
              {label}
            </Text>
          ) : null}
        </View>
      </Touchable>
    </Elevation>
  );
};

const styles = StyleSheet.create({
  button: {
    borderStyle: "solid",
  },
  content: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "center",
  },
  icon: {
    alignItems: "center",
    justifyContent: "center",
    width: Config.buttonIconSize,
  },
  fixed: {
    left: 0,
    right: 0,
    bottom: 0,
    height: 64,
    borderRadius: 0,
  },
});

export default withTheme(FAB);