import React, { useMemo } from 'react';
import PropTypes from 'prop-types';
import withListener from '../withListener';
import ProductCard from '../../atoms/product-card/ProductCard';
import ButtonsList, { callToActionsShape } from '../../atoms/buttons-list/ButtonsList';
import BreadCrumbs from '../../atoms/bread-crumbs/BreadCrumbs';
import './styles/ProductBanner.scss';
import { createNamespace } from '../../tools/namingTools';
import { parseToBool } from '../../tools/helpers';
import { unescapeHtml } from '../../tools/stringTools';
import { COLORPICKER, DROPDOWN, IMAGE_UPLOADER, RADIO, GROUP_HEADER, TOGGLE } from '../../constants/schemaComponentTypes';
import { BACKGROUND_COLOR, BACKGROUND_IMAGE } from '../../constants/backgroundSettings';
import { SMALL, MEDIUM, LARGE } from '../../constants/sizes';
import { parsePricingActions } from '../../tools/callToActions';
import { LIGHT, DARK } from '../../constants/themeColor';

const n = createNamespace('ProductBanner');

const AVAILABLE_TYPES = [BACKGROUND_IMAGE.value];

export const ProductBannerComponent = ({
    settings,
    data: { summary, relatedContent, callToActions = { items: [] }, categories, listingPageUrl, i18n }
}) => {
    // build the crumb's back button link. If we come from a listing page, clicking back will go history -1.
    // Otherwise (for example if we come from an external site) the crumb's root will be a link to the listings page
    const breadcrumbRoot = useMemo(() => {
        if (!listingPageUrl) {
            return {};
        }
        const { referrer } = document;
        // we come from a listings page
        if (referrer.indexOf(listingPageUrl) !== -1) {
            return {
                baseLinkText: i18n && i18n.backLinkLabel,
                baseLinkAction: () => window.history.go(-1)
            };
        }

        return {
            baseLinkText: i18n && i18n.listingLinkLabel,
            baseLinkUrl: listingPageUrl
        };
    }, [listingPageUrl, i18n]);

    if (!summary) {
        return null;
    }

    const settingsWithDefaults = { ...ProductBannerComponent.defaultProps.settings, ...settings };
    const {
        backgroundType,
        bannerBackgroundColor,
        backgroundImg,
        settingsHeight,
        productNameSize,
        descTextSize,
        textColor
    } = settingsWithDefaults;
    const [showRatings] = parseToBool(settings.showRatings);
    const pricingActions = parsePricingActions(callToActions);

    const textSettings = {
        showRatings,
        settingsHeight,
        productNameSize,
        descTextSize,
        textColor
    };

    const hasButtons = Boolean(pricingActions && pricingActions.items && pricingActions.items.length);

    const containerModifiers = [
        settingsHeight && settingsHeight.toLowerCase(),
        textColor && textColor.toLowerCase()
    ];

    const buildBackgroundStyle = () => {
        const imageOrColor = AVAILABLE_TYPES.includes(backgroundType)
            ? { backgroundImage: `url(${unescapeHtml(backgroundImg.url)})` }
            : { backgroundColor: bannerBackgroundColor };

        return Object.assign(
            {},
            imageOrColor
        );
    };

    return (
        <div {...n('container', containerModifiers).withTestId().withE2EId().props}>
            <div
                {...n('backgroundWrapper').withTestId().props}
                style={buildBackgroundStyle()}
            />
            <div {...n('breadCrumbs').props}>
                <BreadCrumbs crumbs={[{ separator: '|', items: categories }]} {...breadcrumbRoot} />
            </div>
            <div {...n('wrapper').props}>
                <div {...n('row').props}>
                    <div {...n('card').props}>
                        <ProductCard
                            cardData={summary}
                            reviewData={relatedContent}
                            settings={textSettings}
                        />
                    </div>
                    {hasButtons && (
                        <div {...n('buttons').props}>
                            <ButtonsList data={{ callToActions: pricingActions, primaryButtonType: 'emphasis' }} />
                        </div>
                    )}
                </div>
            </div>
        </div>
    );
};

const BACKGROUND_TYPE_OPTIONS = [BACKGROUND_IMAGE, BACKGROUND_COLOR];
const SIZE_OPTIONS = [SMALL, MEDIUM, LARGE];
const TEXT_COLOR_OPTIONS = [LIGHT, DARK];

ProductBannerComponent.schema = () => ({
    name: 'ProductBanner',
    title: 'uieditor.sfbComponent.productBanner.title',
    iconName: 'banner',
    form: {
        spacer: {
            type: GROUP_HEADER,
            title: 'uieditor.sfbComponent.productBanner.spacer.title',
            symbol: 'style'
        },
        backgroundType: {
            title: 'uieditor.sfbComponent.productBanner.backgroundType.title',
            type: RADIO,
            required: false,
            defaultValue: BACKGROUND_TYPE_OPTIONS[1].value,
            options: BACKGROUND_TYPE_OPTIONS,
            validation: {
                availableOptions: BACKGROUND_TYPE_OPTIONS.map(({ value }) => value),
                message: 'uieditor.sfbComponent.radio.validation.message',
                default: 'uieditor.sfbComponent.dropdown.defaultValue'
            }
        },
        backgroundImg: {
            title: 'uieditor.sfbComponent.productBanner.backgroundImg.title',
            caption: 'uieditor.sfbComponent.productBanner.backgroundImg.caption',
            placeholder: 'uieditor.sfbComponent.productBanner.backgroundImg.placeholder',
            defaultValue: {
                filename: 'background-image',
                type: 'IMAGE_UPLOADER',
                url: ''
            },
            type: IMAGE_UPLOADER,
            required: false,
            conditionalAttributes: {
                isDisabled: {
                    when: 'backgroundType',
                    connector: 'equals',
                    value: BACKGROUND_COLOR.value
                }
            }
        },
        bannerBackgroundColor: {
            title: 'uieditor.sfbComponent.productBanner.bannerBackgroundColor.title',
            defaultValue: '#ffffff',
            type: COLORPICKER,
            conditionalAttributes: {
                isDisabled: {
                    when: 'backgroundType',
                    connector: 'equals',
                    value: BACKGROUND_IMAGE.value
                }
            }
        },
        textColor: {
            title: 'uieditor.sfbComponent.productBanner.textColor.title',
            type: DROPDOWN,
            required: true,
            defaultValue: TEXT_COLOR_OPTIONS[1].value,
            options: TEXT_COLOR_OPTIONS,
            validation: {
                availableOptions: TEXT_COLOR_OPTIONS.map(({ value }) => value),
                message: 'uieditor.sfbComponent.dropdown.validation.message',
                default: 'uieditor.sfbComponent.dropdown.defaultValue'
            }
        },
        spacer3: {
            type: GROUP_HEADER,
            title: 'uieditor.sfbComponent.productBanner.spacer3.title',
            symbol: 'settings'
        },
        settingsHeight: {
            title: 'uieditor.sfbComponent.productBanner.settingsHeight.title',
            type: DROPDOWN,
            required: true,
            defaultValue: SIZE_OPTIONS[1].value,
            options: SIZE_OPTIONS,
            validation: {
                availableOptions: SIZE_OPTIONS.map(({ value }) => value),
                message: 'uieditor.sfbComponent.dropdown.validation.message',
                default: 'uieditor.sfbComponent.dropdown.defaultValue'
            }
        },
        showRatings: {
            labelOn: 'uieditor.sfbComponent.productBanner.showRatings.labelOn',
            labelOff: 'uieditor.sfbComponent.productBanner.showRatings.labelOff',
            defaultValue: true,
            type: TOGGLE
        },
        productNameSize: {
            title: 'uieditor.sfbComponent.productBanner.productNameSize.title',
            type: DROPDOWN,
            required: true,
            defaultValue: SIZE_OPTIONS[1].value,
            options: SIZE_OPTIONS,
            validation: {
                availableOptions: SIZE_OPTIONS.map(({ value }) => value),
                message: 'uieditor.sfbComponent.dropdown.validation.message',
                default: 'uieditor.sfbComponent.dropdown.defaultValue'
            }
        },
        descTextSize: {
            title: 'uieditor.sfbComponent.productBanner.descTextSize.title',
            type: DROPDOWN,
            required: true,
            defaultValue: SIZE_OPTIONS[1].value,
            options: SIZE_OPTIONS,
            validation: {
                availableOptions: SIZE_OPTIONS.map(({ value }) => value),
                message: 'uieditor.sfbComponent.dropdown.validation.message',
                default: 'uieditor.sfbComponent.dropdown.defaultValue'
            }
        }
    },
    marketplaceData: {
        summary: 'application.summary',
        configurator: 'application.configurator',
        relatedContent: 'application.relatedContent',
        callToActions: 'application.callToActions',
        categories: 'application.categories.items',
        listingPageUrl: 'config.listingEndpoint',
        i18n: 'i18n'
    }
});

ProductBannerComponent.propTypes = {
    settings: PropTypes.shape({
        backgroundType: PropTypes.oneOfType([
            PropTypes.string,
            PropTypes.object
        ]),
        bannerBackgroundColor: PropTypes.string,
        textColor: PropTypes.oneOf(TEXT_COLOR_OPTIONS.map(({ value }) => value)),
        backgroundImg: PropTypes.shape({
            filename: PropTypes.string,
            type: PropTypes.oneOf([IMAGE_UPLOADER]),
            url: PropTypes.string
        }),
        showRatings: PropTypes.bool,
        settingsHeight: PropTypes.string,
        productNameSize: PropTypes.oneOf(SIZE_OPTIONS.map(({ value }) => value)),
        descTextSize: PropTypes.oneOf(SIZE_OPTIONS.map(({ value }) => value))
    }),
    data: PropTypes.shape({
        summary: PropTypes.shape({
            title: PropTypes.string,
            details: PropTypes.string,
            logoSrc: PropTypes.string,
            logoSrcset: PropTypes.shape({
                default: PropTypes.string,
                '1x': PropTypes.string,
                '2x': PropTypes.string
            }),
            merchandisingBadges: PropTypes.arrayOf(
                PropTypes.shape({
                    uuid: PropTypes.string,
                    name: PropTypes.string,
                    image: PropTypes.string
                })
            )
        }),
        categories: PropTypes.arrayOf(
            PropTypes.shape({
                label: PropTypes.string,
                href: PropTypes.string
            })
        ),
        listingPageUrl: PropTypes.string,
        callToActions: PropTypes.shape(callToActionsShape),
        configurator: PropTypes.shape({
            url: PropTypes.string
        }),
        relatedContent: PropTypes.shape({
            details: PropTypes.shape({
                reviews: PropTypes.shape({
                    rating: PropTypes.number,
                    numRatings: PropTypes.number
                }),
                vendor: PropTypes.shape({
                    title: PropTypes.string,
                    items: PropTypes.arrayOf(PropTypes.shape({
                        label: PropTypes.string
                    }))
                })
            })
        }),
        i18n: PropTypes.shape({
            backLinkLabel: PropTypes.string,
            listingLinkLabel: PropTypes.string
        })
    })
};

const SETTINGS = ProductBannerComponent.schema().form;

ProductBannerComponent.defaultProps = {
    settings: {
        backgroundType: SETTINGS.backgroundType.defaultValue,
        bannerBackgroundColor: SETTINGS.bannerBackgroundColor.defaultValue,
        textColor: SETTINGS.textColor.defaultValue,
        backgroundImg: SETTINGS.backgroundImg.defaultValue,
        showRatings: SETTINGS.showRatings.defaultValue,
        settingsHeight: SETTINGS.settingsHeight.defaultValue,
        productNameSize: SETTINGS.productNameSize.defaultValue,
        descTextSize: SETTINGS.descTextSize.defaultValue
    },
    data: {
        summary: null,
        configurator: {
            url: ''
        },
        callToActions: null,
        relatedContent: {
            details: {
                reviews: {
                    rating: 0,
                    numRatings: 0
                },
                vendor: {
                    title: '',
                    items: [
                        {
                            label: ''
                        }
                    ]
                }
            }
        },
        i18n: null,
        categories: null
    }
};

export default withListener(ProductBannerComponent);
