import React, { useRef, useState } from 'react';
import PropTypes from 'prop-types';
import isEmpty from 'lodash/isEmpty';
import cloneDeep from 'lodash/cloneDeep';
import { withStyles } from '@material-ui/core/styles';
import withWidth from '@material-ui/core/withWidth';
import SelectionToolbox from 'redhotmagma-graphics-editor/Components/SelectionToolbox/SelectionToolbox';
import ReactComponent from 'Shared/PropTypes/ReactComponent';
import TextControlbox from '../TextControlbox';
import ImageControlbox from '../ImageControlbox';
import { CustomFontOverlay } from './CustomFontOverlay';
import { createFontItemProps, findCurrentFontItem } from './fontItemUtils';
import { isPlaceholderContent, isOneLineText } from 'App/Reducers/DesignArea/Selectors';
import isMobileDevice from 'Framework/Helpers/isMobileDevice';
import { hasBackgroundColor } from 'App/Reducers/DesignData/Selectors';
import { t } from 'Framework/i18n';
import { isOriginalVector } from '../../Utils/Transformers';
import { useSelector } from 'react-redux';

const styles = theme => ({
    root: {
        marginTop: theme.spacing(2),
        marginBottom: theme.spacing(2),

        [theme.orientation.portrait]: {
            marginTop: 'auto',
            marginBottom: 0,
        },
    },
    disableTextEditor: {
        userSelect: 'none',
    },
});

const isButtonDisabled = (isBold, isItalic, fontItem, action) =>
    getFontNextState(
        isBold,
        isItalic,
        fontItem.regular,
        fontItem.bold,
        fontItem.italic,
        fontItem.boldItalic,
        action
    ) === null;

const getFontNextState = (
    currentBold,
    currentItalic,
    regularAvailable,
    boldAvailable,
    italicAvailable,
    boldItalicAvailable,
    action
) => {
    const acceptableOutcomes = [];

    if (action === 'bold') {
        acceptableOutcomes.push({ bold: !currentBold, italic: currentItalic });
    } else if (action === 'italic') {
        acceptableOutcomes.push({ bold: currentBold, italic: !currentItalic });
    }

    acceptableOutcomes.push({ bold: !currentBold, italic: !currentItalic });

    const availableAcceptableOutcomes = acceptableOutcomes.filter(acceptableOutcome => {
        if (acceptableOutcome.bold) {
            return acceptableOutcome.italic ? boldItalicAvailable : boldAvailable;
        }

        return acceptableOutcome.italic ? italicAvailable : regularAvailable;
    });

    return availableAcceptableOutcomes.length ? availableAcceptableOutcomes[0] : null;
};

const handleObjectButtonClick = (evt, canvas, onMoveUpClick, onMoveDownClick) => {
    switch (evt.currentTarget.value) {
        case 'remove': {
            canvas.selectedObject.remove();
            break;
        }
        case 'moveUp': {
            onMoveUpClick();
            break;
        }
        case 'moveDown': {
            onMoveDownClick();
            break;
        }
        case 'alignHorizontalCenter': {
            canvas.selectedObject.alignTo(false, 'center');
            break;
        }
        case 'alignVerticalCenter': {
            canvas.selectedObject.alignTo('center', false);
            break;
        }
    }
};

export const isOriginallyVector = object =>
    (object && object.type === 'Image' && isOriginalVector(object.imageData)) || false;

const isRaster = object =>
    (object && object.type === 'Image' && /\.(jpe?g|png|gif)$/i.test(object.src)) || false;

export const getPrintQuality = object => {
    if (!isOriginallyVector(object) && isRaster(object)) {
        if (object.scaling >= 2) {
            return 'poor';
        }
        if (object.scaling > 1) {
            return 'ok';
        }
    }
    return 'great';
};

const DesignerSelectionToolbox = props => {
    const {
        classes,
        width,
        openImageEditDialog,
        TextControlboxComponent,
        ImageControlboxComponent,
        CustomFontOverlayComponent,
        colorDisabled,
        fonts: fontFamilyList,
        isActiveBulkName,
        getTextContent,
        isPortraitMode,
        addCustomFont,
        defaultFont,
        loadFonts,
        initialColor,
        autoFocusEditor,
        alignVerticalCenterIcon,
        alignHorizontalCenterIcon,
        moveDownIcon,
        moveUpIcon,
        formatAlignLeftIcon,
        formatAlignCenterIcon,
        formatAlignRightIcon,
        formatAlignJustifyIcon,
        formatBoldIcon,
        formatItalicIcon,
    } = props;

    const rteRef = useRef(null);
    const editorRef = useRef(null);
    const [showCustomFontOverlay, toggleCustomFontOverlay] = useState(false);
    const disableLinebreaks = useSelector(state => isOneLineText(state));

    return (
        <div className={classes.root}>
            <SelectionToolbox>
                {({ canvas, selectedObject, onMoveUpClick, onMoveDownClick, components: { TextTools } }) => {
                    if (selectedObject.type === 'Text') {
                        return (
                            <TextTools
                                selectedObject={selectedObject}
                                canvas={canvas}
                                fullTextCommandList={['fontSize', 'fontFamily']}
                                withStateProvider
                                fontFamilyList={fontFamilyList}
                                rteRef={rteRef}
                                editorRef={editorRef}
                            >
                                {textToolsRenderObj => {
                                    const {
                                        canvas,
                                        selectedObject,
                                        classes: textToolsClasses,
                                        renderTextEditor,
                                        onChangeHTML,
                                        textEditorState: { formatDoc, getStyleValues },
                                        fontFamilyList,
                                    } = textToolsRenderObj;
                                    const { isBold, isItalic, textAlign, fontSize } = getStyleValues();
                                    const color = isEmpty(initialColor)
                                        ? cloneDeep(getStyleValues().color)
                                        : initialColor;
                                    const editorBackgroundColor = hasBackgroundColor(
                                        selectedObject.style.colors.length > 0
                                            ? selectedObject.style.colors
                                            : [color]
                                    )
                                        ? '#C4C4C4'
                                        : '#FFFFFF';

                                    const currentFontItem = findCurrentFontItem(
                                        fontFamilyList,
                                        selectedObject.fontItem
                                    );

                                    // add custom font item
                                    const translatedAddCustomFont = t('textControlbox.addCustomFont');
                                    const addCustomFontItem = {
                                        name: translatedAddCustomFont,
                                        value: translatedAddCustomFont,
                                    };
                                    const fontsList = [...fontFamilyList, addCustomFontItem];

                                    return (
                                        <React.Fragment>
                                            <TextControlboxComponent
                                                selectedObject={selectedObject}
                                                isActiveBulkName={isActiveBulkName}
                                                boxed={width !== 'xs'}
                                                isPortraitMode={isPortraitMode}
                                                textValue={selectedObject.content}
                                                handleChangeText={onChangeHTML}
                                                fontValue={currentFontItem}
                                                fonts={fontsList}
                                                editorBackgroundColor={editorBackgroundColor}
                                                color={color}
                                                handleChangeFont={evt => {
                                                    const fontItem = evt.target.value;

                                                    if (fontItem === addCustomFontItem) {
                                                        toggleCustomFontOverlay(true);
                                                        return;
                                                    }

                                                    canvas.selectedObject.fontItem = createFontItemProps(
                                                        fontItem
                                                    );
                                                }}
                                                minSize={selectedObject.fontSizeMin}
                                                maxSize={1000}
                                                fontSizeValue={parseInt(fontSize)}
                                                onChangeFontSize={value =>
                                                    formatDoc('fontSize', `${value}px`)
                                                }
                                                handleButtonClick={evt => {
                                                    const command = evt.currentTarget.value;

                                                    if (command === 'bold' || command === 'italic') {
                                                        const font = currentFontItem;

                                                        const fontNextState = getFontNextState(
                                                            isBold,
                                                            isItalic,
                                                            font.regular,
                                                            font.bold,
                                                            font.italic,
                                                            font.boldItalic,
                                                            command
                                                        );

                                                        if (fontNextState === null) {
                                                            return;
                                                        }

                                                        if (fontNextState.bold !== isBold) {
                                                            formatDoc('bold');
                                                        }

                                                        if (fontNextState.italic !== isItalic) {
                                                            formatDoc('italic');
                                                        }

                                                        return;
                                                    }

                                                    formatDoc(command);
                                                }}
                                                handleObjectButtonClick={evt => {
                                                    handleObjectButtonClick(
                                                        evt,
                                                        canvas,
                                                        onMoveUpClick,
                                                        onMoveDownClick
                                                    );
                                                }}
                                                flipToBackDisabled={selectedObject.isFirst}
                                                flipToFrontDisabled={selectedObject.isLast}
                                                renderEditorComponent={() => {
                                                    const textEditorElementProps = {
                                                        onFocus: () => {
                                                            if (
                                                                isPlaceholderContent(selectedObject.content)
                                                            ) {
                                                                canvas.selectedObject.content = '';
                                                            }
                                                        },
                                                        onBlur: () => {
                                                            const regex = /<\/span>/;
                                                            if (selectedObject.content.search(regex) === -1) {
                                                                canvas.selectedObject.remove();
                                                            }
                                                        },
                                                    };

                                                    if (selectedObject.isBulkName) {
                                                        Object.assign(textEditorElementProps, {
                                                            contentEditable: false,
                                                            className: [
                                                                textToolsClasses.textEditorContent,
                                                                classes.disableTextEditor,
                                                            ].join(' '),
                                                        });
                                                    }

                                                    return renderTextEditor({
                                                        ...textToolsRenderObj,
                                                        disableLinebreaks,
                                                        autoFocusWhenMounted:
                                                            autoFocusEditor ||
                                                            !(
                                                                isPlaceholderContent(
                                                                    selectedObject.content
                                                                ) || isMobileDevice()
                                                            ),
                                                        textEditorElementProps,
                                                        onChangeHTML: (...args) => {
                                                            // call the original function first with all the args
                                                            textToolsRenderObj.onChangeHTML(...args);
                                                            // reload the fonts
                                                            loadFonts(canvas.selectedObject);
                                                        },
                                                    });
                                                }}
                                                isBold={isBold}
                                                boldDisabled={isButtonDisabled(
                                                    isBold,
                                                    isItalic,
                                                    currentFontItem,
                                                    'bold'
                                                )}
                                                isItalic={isItalic}
                                                italicDisabled={isButtonDisabled(
                                                    isBold,
                                                    isItalic,
                                                    currentFontItem,
                                                    'italic'
                                                )}
                                                textAlign={textAlign}
                                                colorDisabled={colorDisabled}
                                                isBulkName={selectedObject.isBulkName}
                                                toggleIsBulkName={() => {
                                                    const isBulkName = !selectedObject.isBulkName;
                                                    canvas.selectedObject.isBulkName = isBulkName;
                                                    canvas.selectedObject.content = getTextContent({
                                                        isBulkName,
                                                    });
                                                }}
                                                alignVerticalCenterIcon={alignVerticalCenterIcon}
                                                alignHorizontalCenterIcon={alignHorizontalCenterIcon}
                                                moveDownIcon={moveDownIcon}
                                                moveUpIcon={moveUpIcon}
                                                formatAlignLeftIcon={formatAlignLeftIcon}
                                                formatAlignCenterIcon={formatAlignCenterIcon}
                                                formatAlignRightIcon={formatAlignRightIcon}
                                                formatAlignJustifyIcon={formatAlignJustifyIcon}
                                                formatBoldIcon={formatBoldIcon}
                                                formatItalicIcon={formatItalicIcon}
                                            />
                                            <CustomFontOverlayComponent
                                                onClose={() => toggleCustomFontOverlay(false)}
                                                open={showCustomFontOverlay}
                                                onApply={fontName => {
                                                    const fontItem = {
                                                        ...defaultFont,
                                                        customName: fontName,
                                                        isCustomFont: true,
                                                    };
                                                    addCustomFont(fontItem);
                                                    canvas.selectedObject.fontItem = createFontItemProps(
                                                        fontItem
                                                    );
                                                    toggleCustomFontOverlay(false);
                                                }}
                                            />
                                        </React.Fragment>
                                    );
                                }}
                            </TextTools>
                        );
                    } else if (selectedObject.type === 'Image' || selectedObject.type === 'Group') {
                        return (
                            <ImageControlboxComponent
                                canvas={canvas}
                                boxed={width !== 'xs'}
                                imageData={selectedObject.imageData}
                                printQuality={getPrintQuality(selectedObject)}
                                openImageEditDialog={openImageEditDialog}
                                handleObjectButtonClick={evt => {
                                    handleObjectButtonClick(evt, canvas, onMoveUpClick, onMoveDownClick);
                                }}
                                flipToBackDisabled={selectedObject.isFirst}
                                flipToFrontDisabled={selectedObject.isLast}
                                alignVerticalCenterIcon={alignVerticalCenterIcon}
                                alignHorizontalCenterIcon={alignHorizontalCenterIcon}
                                moveDownIcon={moveDownIcon}
                                moveUpIcon={moveUpIcon}
                            />
                        );
                    } else {
                        // do not show control box for unknown object types
                        return null;
                    }
                }}
            </SelectionToolbox>
        </div>
    );
};

DesignerSelectionToolbox.propTypes = {
    updateVisualization: PropTypes.func.isRequired,
    openImageEditDialog: PropTypes.func.isRequired,
    loadFonts: PropTypes.func.isRequired,
    TextControlboxComponent: ReactComponent,
    ImageControlboxComponent: ReactComponent,
    CustomFontOverlayComponent: PropTypes.elementType,
    fonts: PropTypes.array,
    colorDisabled: PropTypes.bool,
    classes: PropTypes.shape({
        root: PropTypes.string,
        disableTextEditor: PropTypes.string,
    }),
    width: PropTypes.string,
    isActiveBulkName: PropTypes.bool,
    getTextContent: PropTypes.func,
    isPortraitMode: PropTypes.bool,
    calculateTextEditorBackgroundColor: PropTypes.func,
    addCustomFont: PropTypes.func,
    defaultFont: PropTypes.object,
    initialColor: PropTypes.object,
    autoFocusEditor: PropTypes.bool,
    alignVerticalCenterIcon: PropTypes.element,
    alignHorizontalCenterIcon: PropTypes.element,
    moveDownIcon: PropTypes.element,
    moveUpIcon: PropTypes.element,
    formatAlignLeftIcon: PropTypes.element,
    formatAlignCenterIcon: PropTypes.element,
    formatAlignRightIcon: PropTypes.element,
    formatAlignJustifyIcon: PropTypes.element,
    formatBoldIcon: PropTypes.element,
    formatItalicIcon: PropTypes.element,
};

DesignerSelectionToolbox.defaultProps = {
    TextControlboxComponent: TextControlbox,
    ImageControlboxComponent: ImageControlbox,
    CustomFontOverlayComponent: CustomFontOverlay,
    fonts: [],
    colorDisabled: false,
    classes: {},
    width: '',
    isActiveBulkName: false,
    isPortraitMode: false,
    autoFocusEditor: false,
};

export default withWidth()(
    withStyles(styles, { name: 'DesignerSelectionToolbox' })(DesignerSelectionToolbox)
);
