import React from 'react';
import PropTypes from 'prop-types';
import { createNamespace } from '../../tools/namingTools';
import { TYPE_SUBMIT, ATTR_REFER_URL, TARGET_BLANK, REL_NOOPENER } from '../../constants/buttons';
import { allowedThemes as buttonThemes, allowedActions as buttonActions, allowedSizes as buttonSizes, allowedTypes as buttonTypes } from '../button/Button';
import { LEFT, RIGHT } from '../../constants/alignment';
import { ALLOWED_CTA_TYPES, CTA_REFERABLE } from '../../constants/actions';
import Icon, { allowedTypes as iconTypes } from '../icon/Icon';
import Image from '../image/Image';
import './styles/ButtonIcon.scss';

const n = createNamespace('ButtonIcon');

const ButtonIcon = ({
    action,
    children,
    ctaType,
    disabled,
    hiddenText,
    icon,
    iconClass,
    textClass,
    iconPosition,
    iconSrc,
    onBlur,
    onClick,
    onFocus,
    buttonRef,
    onMouseLeave,
    onMouseOver,
    referUrl,
    selected,
    size,
    theme,
    type,
    url,
    openUrlInNewTab,
    className: extraClass,
    ...otherProps
}) => {
    const modifiers = [
        type,
        selected && 'selected',
        size && `size-${size}`,
        icon && iconPosition && `icon-${iconPosition}`,
        [type, theme].filter(Boolean).join('-')
    ];

    const onClickHandler = e => {
        if (disabled) { return; }
        if (url && openUrlInNewTab) {
            window.open(url, TARGET_BLANK, REL_NOOPENER);
        } else if (url && action !== TYPE_SUBMIT) {
            window.location.replace(url);
        }
        if (onClick) {
            onClick(e);
        }
    };

    const buttonProps = {
        ...n('button', modifiers).withTestId().withE2EId().withClass(extraClass).props,
        type: action,
        disabled,
        onClick: onClickHandler,
        'data-cta-type': ctaType,
        'data-href': url,
        onMouseOver,
        onMouseLeave,
        onFocus,
        onBlur,
        ref: buttonRef,
        ...otherProps
    };

    if (referUrl && ctaType === CTA_REFERABLE) {
        buttonProps[ATTR_REFER_URL] = referUrl;
    }

    const buttonTextModifiers = [
        hiddenText && 'hidden'
    ];

    const renderIcon = () => {
        const iconModifiers = [
            iconPosition,
            size,
            icon,
            iconSrc && 'external'
        ];
        const props = { ...n('icon', iconModifiers).withTestId().withClass(iconClass).props };

        if (icon) {
            return <Icon {...props} type={icon} />;
        }

        if (iconSrc) {
            return <Image {...props} src={iconSrc} />;
        }

        return null;
    };

    return (
        /* eslint-disable react/button-has-type */
        <button {...buttonProps}>
            {renderIcon()}
            {children && (
                <span {...n('text', buttonTextModifiers).withClass(textClass).withTestId().props}>
                    {React.Children.map(children, child => child)}
                </span>
            )}
        </button>
    );
};

ButtonIcon.propTypes = {
    action: PropTypes.oneOf(buttonActions),
    ctaType: PropTypes.oneOf(ALLOWED_CTA_TYPES),
    disabled: PropTypes.bool,
    hiddenText: PropTypes.bool,
    icon: PropTypes.oneOf(iconTypes),
    iconClass: PropTypes.string,
    textClass: PropTypes.string,
    iconPosition: PropTypes.oneOf([LEFT.value, RIGHT.value]),
    iconSrc: PropTypes.string,
    onBlur: PropTypes.func,
    onClick: PropTypes.func,
    onFocus: PropTypes.func,
    onMouseLeave: PropTypes.func,
    onMouseOver: PropTypes.func,
    referUrl: PropTypes.string,
    selected: PropTypes.bool,
    size: PropTypes.oneOf(buttonSizes),
    theme: PropTypes.oneOf(buttonThemes),
    type: PropTypes.oneOf(buttonTypes),
    className: PropTypes.string,
    url: PropTypes.string,
    openUrlInNewTab: PropTypes.bool,
    buttonRef: PropTypes.func
};

ButtonIcon.defaultProps = {
    action: buttonActions[0],
    ctaType: null,
    disabled: false,
    hiddenText: false,
    icon: null,
    iconClass: null,
    textClass: null,
    iconPosition: LEFT.value,
    iconSrc: null,
    onBlur: () => {},
    onClick: () => {},
    onFocus: () => {},
    onMouseLeave: () => {},
    onMouseOver: () => {},
    referUrl: null,
    selected: false,
    size: null,
    theme: null,
    type: buttonTypes[0],
    className: null,
    url: null,
    openUrlInNewTab: false,
    buttonRef: null
};

export default ButtonIcon;
