import {
    type FC
} from "react";
import {
    TouchableOpacity,
    View
} from "react-native";
import type IButtonProps from "./type";
import stylesheet, {
    getButtonVariant,
    getButtonSize,
    getButtonType,
    useStyles
} from "./stylesheet";
import {
    NCoreUIKitTheme
} from "../../core/hooks";
import type ITextProps from "../text/type";
import Loading from "../loading";
import Text from "../text";

/**
 * A generic button
 * @param props {@link IButtonProps}
 * @returns Element
 */
const Button: FC<IButtonProps> = ({
    displayBehaviourWhileLoading = "disabled",
    spreadBehaviour = "baseline",
    isCustomPadding = false,
    icon: IconComponentProp,
    iconDirection = "left",
    variant = "filled",
    isDisabled = false,
    type = "primary",
    size = "medium",
    customTheme,
    titleStyle,
    isLoading,
    onPress,
    title,
    style,
    ...props
}) => {
    const {
        typography,
        radiuses,
        borders,
        colors,
        spaces
    } = NCoreUIKitTheme.useContext(customTheme);

    const currentSize = getButtonSize({
        spaces,
        size
    });

    const currentVariant = getButtonVariant({
        variant,
    });

    const currentType = getButtonType({
        type,
    });

    const {
        container: containerDynamicStyle,
        loading: loadingDynamicStyle,
        overlay: overlayDynamicStyle,
        title: titleDynamicStyle
    } = useStyles({
        displayBehaviourWhileLoading,
        icon: IconComponentProp,
        isCustomPadding,
        spreadBehaviour,
        currentVariant,
        iconDirection,
        currentType,
        currentSize,
        isDisabled,
        isLoading,
        radiuses,
        variant,
        borders,
        colors,
        spaces,
        title,
        type
    });

    const titleProps: ITextProps = {
        color: currentType.titleColor,
    };

    const iconProps: NCoreUIKit.IconCallbackProps = {
        size: Number(typography[currentSize.fontSize].fontSize),
        color: currentType.iconColor
    };

    if (currentVariant.titleColor !== "type") {
        titleProps.color = currentType.titleColor;
    }

    if (currentVariant.iconColor !== "type") {
        iconProps.color = currentType.iconColor;
    }

    if (type === "primary" && variant === "filled") {
        iconProps.color = "onPrimary";
        titleProps.color = "onPrimary";
    }

    if (type === "primary" && variant !== "filled") {
        iconProps.color = "emphasized";
        titleProps.color = "emphasized";
    }

    if (isDisabled || isLoading) {
        const stateType = type === "danger" ? "error" : type;

        titleProps.customColor = colors.system.state.content.disabled[stateType];
        iconProps.customColor = colors.system.state.content.disabled[stateType];
    }

    const renderIcon = () => {
        if (isLoading) {
            return <Loading
                {...iconProps}
                style={[
                    loadingDynamicStyle
                ]}
            />;
        }

        if (!IconComponentProp) {
            return null;
        }

        return <IconComponentProp {...iconProps} />;
    };

    const renderTitle = () => {
        if (!title) {
            return null;
        }

        return <Text
            variant={currentSize.fontSize}
            style={[
                titleStyle,
                stylesheet.title,
                titleDynamicStyle
            ]}
            {...titleProps}
        >
            {title}
        </Text>;
    };

    const renderOverlay = () => {
        return <View
            style={[
                stylesheet.loading,
                stylesheet.overlay,
                overlayDynamicStyle
            ]}
        />;
    };

    return <TouchableOpacity
        {...props}
        onPress={isDisabled || isLoading ? () => null : onPress}
        disabled={isDisabled || isLoading}
        style={[
            style,
            stylesheet.container,
            containerDynamicStyle
        ]}
    >
        {renderIcon()}
        {renderTitle()}

        {renderOverlay()}
    </TouchableOpacity>;
};
export default Button;
