import React from 'react';
import PropTypes from 'prop-types';
import Button from '../../atoms/button/Button';
import Rating from '../../atoms/rating/Rating';
import CheckboxGroup from '../../atoms/checkbox-group/CheckboxGroup';
import Checkbox from '../../atoms/checkbox/Checkbox';
import withListener from '../withListener';

import SlidingPanel from '../../atoms/sliding-panel/SlidingPanel';
import { createNamespace } from '../../tools/namingTools';
import { lowerFirst } from '../../tools/stringTools';
import { TOGGLE, DROPDOWN, COLORPICKER, SLIDER } from '../../constants/schemaComponentTypes';
import { MAX_RATING } from '../../constants/ratings';
import { SMALL, MEDIUM, LARGE } from '../../constants/sizes';
import { RATING_QUERY_KEY } from '../../constants/urlParams';
import { filtersPropTypes } from '../../constants/prop-types/listingFilters/filters';
import { i18nPropTypes } from '../../constants/prop-types/listingFilters/i18n';

import useCategorySidebarState from './hooks/useCategorySidebarState';

import { productListControlsStore } from '../../store/productListControls';

import './styles/CategorySidebar.scss';

const nameSpace = 'CategorySidebar';
const n = createNamespace(nameSpace);

// filter ids
const ATTRIBUTES_FILTER_ID = 'attributes';

export const CategorySidebarComponent = ({
    data: {
        items,
        i18n
    },
    settings: {
        sidebarHeight,
        displayDividers,
        displaySubcategories,
        displayRatings,
        displayAttributes,
        backgroundColor,
        borderColor,
        headerBackgroundColor,
        displayHeaderBorder,
        headerBorderColor,
        sectionHeaderPadding
    }
}) => {
    const i18nWithDefaults = { ...CategorySidebarComponent.defaultProps.data.i18n, ...i18n };
    const sidebarHeightModifier = sidebarHeight ? `size-${lowerFirst(sidebarHeight)}` : '';
    const containerStyle = {
        backgroundColor,
        borderColor
    };
    const sectionHeaderStyle = {
        backgroundColor: headerBackgroundColor,
        borderBottom: displayHeaderBorder ? `1px solid ${headerBorderColor}` : 'none',
        paddingTop: sectionHeaderPadding,
        paddingBottom: sectionHeaderPadding
    };

    const isFieldsetVisible = fieldsetId => {
        switch (fieldsetId) {
            case ATTRIBUTES_FILTER_ID:
                return displayAttributes;
            default:
                return true;
        }
    };

    const { valuesState, onClearFilters,
        onFilterChange, onUpdateRatings } = useCategorySidebarState(items, i18nWithDefaults.ratings);
    const { isFiltersVisible, setFiltersVisible } = productListControlsStore();

    const onClose = e => {
        e.preventDefault();
        setFiltersVisible(false);
    };

    const clearButtonBlock = (
        <div {...n('btnClear').withE2EId().props}>
            <Button type="secondary" size="small" onClick={onClearFilters}>{i18nWithDefaults.clearFilters}</Button>
        </div>
    );

    const dividerModifier = displayDividers && ['divider'];

    const renderFieldset = ({ id, text, items: fieldsetItems }) => {
        const showFieldset = isFieldsetVisible(id);

        return showFieldset && (
            <fieldset key={id} {...n('fieldset', dividerModifier).withTestId().props}>
                <legend {...n('legend').props} style={sectionHeaderStyle}>{text}</legend>
                <div {...n('checkboxGroup').props}>
                    <CheckboxGroup
                        items={fieldsetItems}
                        state={valuesState}
                        prefix={lowerFirst(nameSpace)}
                        isDisplayChildren={displaySubcategories}
                        onChange={onFilterChange}
                    />
                </div>
            </fieldset>
        );
    };

    const renderRatings = () => {
        const ratingOptions = MAX_RATING ? [...Array(MAX_RATING + 1).keys()].reverse() : [];
        const ratingsI18n = {
            ratings: i18nWithDefaults.ratings,
            andUp: i18nWithDefaults.andUp
        };

        return ratingOptions && !!ratingOptions.length && (
            <fieldset {...n('fieldset', dividerModifier).withTestId().props}>
                <legend {...n('legend').props} style={sectionHeaderStyle}>{i18nWithDefaults.ratings}</legend>
                {ratingOptions && (
                    <div {...n('checkboxGroup').props}>
                        {ratingOptions.map(nStars => {
                            if (!nStars) {
                                return null;
                            }

                            const label = (
                                <div {...n('ratingLabel').props}>
                                    <Rating
                                        rating={nStars}
                                        ratingScore={MAX_RATING}
                                        displayRatingNumber={false}
                                        i18n={ratingsI18n}
                                        title={i18nWithDefaults[`rating${nStars}`]}
                                        displayRatingCaption
                                    />
                                </div>
                            );

                            const isChecked = (
                                valuesState[RATING_QUERY_KEY]
                                && valuesState[RATING_QUERY_KEY].length
                                && valuesState[RATING_QUERY_KEY] <= nStars
                            ) || false;

                            return (
                                <Checkbox
                                    key={nStars}
                                    name={`rating_${nStars}`}
                                    ariaLabel={`${nStars} ${i18nWithDefaults.andUp}`}
                                    label={label}
                                    isChecked={isChecked}
                                    onChange={e => onUpdateRatings({
                                        nStars,
                                        isChecked: e ? e.currentTarget.checked : false
                                    })}
                                />
                            );
                        })}
                    </div>
                )}
            </fieldset>
        );
    };

    return (
        <SlidingPanel
            onClose={onClose}
            isVisible={isFiltersVisible}
            i18n={{ closePanel: i18nWithDefaults.close }}
        >
            <aside {...n('wrapper').props}>
                <div {...n('headerMobile').props}>
                    <span {...n('title').props}>{i18nWithDefaults.filters}</span>
                </div>

                <div
                    {...n('container', sidebarHeightModifier).withTestId().props}
                    style={containerStyle}
                >
                    <div {...n('header').withE2EId().props} style={{ borderColor }}>
                        <span {...n('title').props}>{i18nWithDefaults.filters}</span>
                        {clearButtonBlock}
                    </div>
                    <div {...n('content').props}>
                        <form {...n('form').props} noValidate>
                            {items.map(renderFieldset)}
                            {displayRatings && renderRatings()}
                        </form>
                    </div>
                    <div {...n('footer').props} style={{ borderColor }}>
                        {clearButtonBlock}
                    </div>
                </div>
                <div {...n('footerMobile').props}>
                    <Button type="secondary" size="default" onClick={onClearFilters}>{i18nWithDefaults.clearFilters}</Button>
                    <Button type="primary" size="default" onClick={onClose}>{i18nWithDefaults.apply}</Button>
                </div>
            </aside>
        </SlidingPanel>
    );
};

const SIDEBAR_HEIGHT_OPTIONS = [SMALL, MEDIUM, LARGE];

CategorySidebarComponent.schema = () => ({
    name: 'CategorySidebar',
    title: 'uieditor.sfbComponent.categorySidebar.title',
    iconName: 'categories',
    form: {
        sidebarHeight: {
            title: 'uieditor.sfbComponent.categorySidebar.sidebarHeight.title',
            type: DROPDOWN,
            required: true,
            defaultValue: SIDEBAR_HEIGHT_OPTIONS[2].value,
            options: SIDEBAR_HEIGHT_OPTIONS
        },
        displayDividers: {
            labelOn: 'uieditor.sfbComponent.categorySidebar.displayDividers.labelOn',
            labelOff: 'uieditor.sfbComponent.categorySidebar.displayDividers.labelOff',
            defaultValue: false,
            type: TOGGLE
        },
        displaySubcategories: {
            labelOn: 'uieditor.sfbComponent.categorySidebar.displaySubcategories.labelOn',
            labelOff: 'uieditor.sfbComponent.categorySidebar.displaySubcategories.labelOff',
            defaultValue: true,
            type: TOGGLE
        },
        displayRatings: {
            labelOn: 'uieditor.sfbComponent.categorySidebar.displayRatings.labelOn',
            labelOff: 'uieditor.sfbComponent.categorySidebar.displayRatings.labelOff',
            defaultValue: true,
            type: TOGGLE
        },
        displayAttributes: {
            labelOn: 'uieditor.sfbComponent.categorySidebar.displayAttributes.labelOn',
            labelOff: 'uieditor.sfbComponent.categorySidebar.displayAttributes.labelOff',
            defaultValue: true,
            type: TOGGLE
        },
        backgroundColor: {
            title: 'uieditor.sfbComponent.categorySidebar.backgroundColor.title',
            type: COLORPICKER,
            defaultValue: '#FFFFFF'
        },
        borderColor: {
            title: 'uieditor.sfbComponent.categorySidebar.borderColor.title',
            type: COLORPICKER,
            defaultValue: '#CBCBCB'
        },
        headerBackgroundColor: {
            title: 'uieditor.sfbComponent.categorySidebar.headerBackgroundColor.title',
            type: COLORPICKER,
            defaultValue: 'FFFFFF'
        },
        displayHeaderBorder: {
            labelOn: 'uieditor.sfbComponent.categorySidebar.displayHeaderBorder.labelOn',
            labelOff: 'uieditor.sfbComponent.categorySidebar.displayHeaderBorder.labelOff',
            defaultValue: false,
            type: TOGGLE
        },
        headerBorderColor: {
            title: 'uieditor.sfbComponent.categorySidebar.headerBorderColor.title',
            type: COLORPICKER,
            defaultValue: '#CBCBCB'
        },
        sectionHeaderPadding: {
            title: 'uieditor.sfbComponent.categorySidebar.sectionHeaderPadding.title',
            type: SLIDER,
            required: true,
            defaultValue: 5,
            options: {
                step: 5,
                min: 0,
                max: 35,
                unit: 'px'
            }
        }
    },
    marketplaceData: {
        items: 'listingFilters.filters',
        i18n: 'listingFilters.i18n',
        listing: 'listingProducts'
    }
});

CategorySidebarComponent.propTypes = {
    data: PropTypes.shape({
        items: PropTypes.arrayOf(PropTypes.shape(filtersPropTypes)),
        i18n: PropTypes.shape(i18nPropTypes)
    }),
    settings: PropTypes.shape({
        sidebarHeight: PropTypes.oneOf(SIDEBAR_HEIGHT_OPTIONS.map(({ value }) => value)),
        displayDividers: PropTypes.bool,
        displaySubcategories: PropTypes.bool,
        displayRatings: PropTypes.bool,
        displayAttributes: PropTypes.bool,
        backgroundColor: PropTypes.string,
        borderColor: PropTypes.string,
        headerBackgroundColor: PropTypes.string,
        displayHeaderBorder: PropTypes.bool,
        headerBorderColor: PropTypes.string,
        sectionHeaderPadding: PropTypes.number
    })
};

const SETTINGS = CategorySidebarComponent.schema().form;

CategorySidebarComponent.defaultProps = {
    data: {
        items: [],
        i18n: {
            andUp: '& up',
            apply: 'Apply',
            clearFilters: 'Clear Filters',
            done: 'Done',
            filters: 'Filters',
            hideFilters: 'Hide Filters',
            ratings: 'Ratings',
            showFilters: 'Show Filters',
            unrated: 'Unrated',
            close: 'Close categories sidebar',
            rating1: '1 star & up',
            rating2: '2 star & up',
            rating3: '3 star & up',
            rating4: '4 star & up',
            rating5: '5 stars'
        }
    },
    settings: {
        sidebarHeight: SETTINGS.sidebarHeight.defaultValue,
        displayDividers: SETTINGS.displayDividers.defaultValue,
        displaySubcategories: SETTINGS.displaySubcategories.defaultValue,
        displayRatings: SETTINGS.displayRatings.defaultValue,
        displayAttributes: SETTINGS.displayAttributes.defaultValue,
        backgroundColor: SETTINGS.backgroundColor.defaultValue,
        borderColor: SETTINGS.borderColor.defaultValue,
        headerBackgroundColor: SETTINGS.headerBackgroundColor.defaultValue,
        displayHeaderBorder: SETTINGS.displayHeaderBorder.defaultValue,
        headerBorderColor: SETTINGS.headerBorderColor.defaultValue,
        sectionHeaderPadding: SETTINGS.sectionHeaderPadding.defaultValue
    }
};

export default withListener(CategorySidebarComponent);
