import React, { useMemo } from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';

import Editor from 'redhotmagma-graphics-editor/Components/Editor/Editor';
import DefaultEditorContainer from 'redhotmagma-graphics-editor/Components/Editor/EditorContainer';
import { withAlignTarget } from 'redhotmagma-visualization/AlignTargetProvider';
import { createCheckerBoardBackground } from '../../../Utils/Styles/createCheckerBoardBackground';

const mockUploadFunction = files => {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = () => {
            const dataURL = reader.result;
            resolve([{ src: dataURL }]);
        };
        reader.onerror = reject;
        reader.readAsDataURL(files[0]);
    });
};

const styles = theme => ({
    root: {
        flexShrink: 1,
        flexBasis: '100%',
        display: 'flex',
        flexDirection: 'column',
        maxWidth: '100%',
        alignItems: 'center',
        [theme.breakpoints.down('xs')]: {
            minHeight: '150px',
        },

        // use pseudo elements to achieve vertical middle aligning
        '&:before': {
            content: "''",
            display: 'block',
            marginTop: 'auto',
        },
        '&:after': {
            content: "''",
            display: 'block',
            marginBottom: 'auto',
        },
        // match all the first level child elements that are not the resize-sensor
        '& > :not(.resize-sensor)': {
            /**
             * The pointer events are passed through in the "main" class of DefaultLayout,
             * but the contained elements may need it (like the Designer and its controls)
             * @see DefaultLayout
             */
            pointerEvents: 'all',
        },
    },
    checkerBoardBackground: {
        ...createCheckerBoardBackground({
            darkColor: 'rgba(0, 0, 0, 0.1)',
            lightColor: 'rgba(0, 0, 0, 0.01)',
        }),
    },
});

const CustomEditorContainer = withStyles(
    { closeButton: { position: 'absolute', top: -20, right: -20, cursor: 'pointer' } },
    { name: 'CustomEditorContainer' }
)(({ children, ...props }) => <DefaultEditorContainer {...props}>{children}</DefaultEditorContainer>);

const getCustomEditorStyle = ({ hasBorder }) => {
    const style = {};
    if (!hasBorder) {
        style.borderWidth = 0;
    }
    return style;
};

export const Designer = ({
    renderStandardToolbox,
    renderSelectionToolbox,
    renderInlineToolbox,
    renderRulers,
    canvasSize,
    classes,
    show,
    selectedColor,
    alignTarget,
    EditorContainer,
    hideDesigner,
    hasBorder,
    useCheckerBoardBackground,
    renderInCanvasContainer,
}) => {
    const containerReadyHandler = useMemo(
        () => ({ container }) => {
            alignTarget.add(container);
            // it has to be delayed in the next message, when the correct size is already available
            return () => setTimeout(() => alignTarget.remove(container));
        },
        [alignTarget]
    );

    const containerUpdateHandler = useMemo(
        () => () => {
            // re-add it on update to trigger the change which updates the offset
            setTimeout(() => {
                alignTarget.add(null);
                alignTarget.remove(null);
            });
        },
        [alignTarget]
    );

    const EditorContainerWithInjectedProps = useMemo(
        () => props => <EditorContainer {...props} onClickClose={hideDesigner} />,
        [hideDesigner]
    );

    return (
        show && (
            <div className={classes.root}>
                <Editor
                    style={getCustomEditorStyle({ hasBorder })}
                    containerClassName={useCheckerBoardBackground && classes.checkerBoardBackground}
                    canvasSize={canvasSize}
                    upload={mockUploadFunction}
                    renderStandardToolbox={renderStandardToolbox}
                    renderSelectionToolbox={renderSelectionToolbox}
                    renderInlineToolbox={renderInlineToolbox}
                    renderRulers={renderRulers}
                    subtractSiblingsHeight
                    allowUpScaling
                    selectedColor={selectedColor}
                    onContainerReady={containerReadyHandler}
                    onContainerUpdate={containerUpdateHandler}
                    EditorContainer={EditorContainerWithInjectedProps}
                    renderInCanvasContainer={renderInCanvasContainer}
                />
            </div>
        )
    );
};

Designer.propTypes = {
    renderStandardToolbox: PropTypes.func,
    renderSelectionToolbox: PropTypes.func,
    renderInlineToolbox: PropTypes.func,
    renderRulers: PropTypes.func,
    show: PropTypes.bool,
    EditorContainer: PropTypes.elementType,
    hasBorder: PropTypes.bool,
    selectedColor: PropTypes.string,
    hideDesigner: PropTypes.func,
    alignTarget: PropTypes.shape({
        add: PropTypes.func.isRequired,
        remove: PropTypes.func.isRequired,
    }).isRequired,
    classes: PropTypes.object.isRequired,
    canvasSize: PropTypes.shape({
        width: PropTypes.number.isRequired,
        height: PropTypes.number.isRequired,
        isMetric: PropTypes.bool,
        dpi: PropTypes.number,
    }).isRequired,
    useCheckerBoardBackground: PropTypes.bool,
    renderInCanvasContainer: PropTypes.func,
};

Designer.defaultProps = {
    renderStandardToolbox: null,
    renderSelectionToolbox: null,
    renderInlineToolbox: null,
    show: true,
    hasBorder: true,
    renderRulers: null,
    selectedColor: '',
    hideDesigner: null,
    EditorContainer: CustomEditorContainer,
    useCheckerBoardBackground: false,
};

export default withStyles(styles, { name: 'Designer' })(withAlignTarget(Designer));
