import * as React from 'react';
import PropTypes from 'prop-types';

import ReactComponentType from 'Shared/PropTypes/ReactComponent';

import Header from 'App/Shared/Containers/Header';
import InvalidConfigurationNotice from 'App/Shared/Containers/InvalidConfigurationNotice';
import DesignAreaControlbox from './Containers/DesignAreaControlbox';
import EditDesignButton from './Containers/EditDesignButton';
import CloseGraphicsEditorButton from './Containers/CloseGraphicsEditorButton';
import CloseDesignEditor from './Containers/CloseDesignEditor';
import ImageEditDialog from './Containers/ImageEditDialog';

import {
    DefaultCanvasProvider,
    DefaultCanvasStateProvider,
    DefaultTextEditorStateProvider,
} from 'App/Shared/Providers/DefaultCanvasProvider';
import { DesignerAlignTarget } from '../Visualization/DesignerAlignTarget';
import DefaultLayout from './Layouts/DefaultLayout';
import { PopupArea as DefaultPopupArea } from './Layouts/PopupAreaProvider';
import { TwoSideBottomBar } from './Layouts/Mobile/TwoSideBottomBar';

import Designer from './Containers/Designer';
import DesignerSelectionToolbox from './Containers/DesignerSelectionToolbox';
import AddVisualElement from './Containers/AddVisualElement';
import ScreenPropTypes from '../../Screens/Configurator/ScreenPropTypes';
import FullScreenView from './Components/FullScreenView/FullScreenView';
import DesignerClickAwayListener from './MultilayerComponents/DesignerClickAwayListener';

/**
 * Main Screen of the configurator
 */
export function DesignerScreen(props) {
    const {
        imageOnly,
        showDesigner,
        showProductViewButton,
        fallbackMode,
        is3DvisualMode,
        isPortraitMode,
        renderHeader,
        renderSaveConfiguration,
        renderSendEmail,
        renderPdfDownload,
        renderLoadConfiguration,
        renderError,
        renderAlertMessages,
        renderConfirm,
        renderAmountPrice,
        renderDesigner,
        renderDesignerSelectionToolbox,
        renderDesignerFallback,
        renderVisualization,
        renderDesignAreaControlbox,
        renderEditDesignButton,
        renderInvalidConfigurationNotice,
        renderCloseGraphicsEditorButton,
        renderImageEditDialog,
        renderCloseDesignEditor,
        renderAddVisualElement,
        renderLoader,
        renderLicenseNotice,
        customElements,
        visualizationOverlayMode,

        // Components
        CanvasProvider,
        CanvasStateProvider,
        TextEditorStateProvider,
        Layout,
        PopupArea,
        FallbackVisualization,
    } = props;

    return (
        <CanvasProvider>
            <Layout
                imageOnly={imageOnly}
                isPortraitMode={isPortraitMode}
                renderHeader={renderProps =>
                    renderProps.width === 'xs' && showDesigner ? () => <div /> : renderHeader()
                }
                fallbackMode={fallbackMode}
                showDesigner={showDesigner}
                visualizationOverlayMode={visualizationOverlayMode}
                renderDesigner={
                    visualizationOverlayMode &&
                    (props => (
                        <FallbackVisualization fallbackMode={fallbackMode} showContent={showDesigner}>
                            {showDesigner && renderDesigner({ visualizationOverlayMode, ...props })}
                        </FallbackVisualization>
                    ))
                }
                renderVisualization={() =>
                    renderVisualization({
                        fullScreenViewProps: {
                            Component: FullScreenView,
                            showPreviewButton: !showDesigner,
                        },
                    })
                }
                renderMain={renderProps => (
                    <>
                        {renderProps.width !== 'xs' && isPortraitMode ? (
                            <div className={renderProps.classes.graphicsEditorWrapper}>
                                {showProductViewButton && renderCloseGraphicsEditorButton(renderProps)}
                                {!showDesigner && renderEditDesignButton({ styledButton: false })}
                            </div>
                        ) : null}
                        {renderProps.width === 'xs'
                            ? showDesigner
                                ? renderDesignAreaControlbox(renderProps)
                                : !showProductViewButton && renderEditDesignButton({ styledButton: false })
                            : null}
                        {!fallbackMode && <DesignerAlignTarget />}
                        {!visualizationOverlayMode && (
                            <FallbackVisualization fallbackMode={fallbackMode} showContent={showDesigner}>
                                {showDesigner && renderDesigner()}
                            </FallbackVisualization>
                        )}
                        {renderError()}
                        {renderAlertMessages()}
                        {renderConfirm()}
                        {renderSaveConfiguration()}
                        {renderSendEmail()}
                        {renderPdfDownload()}
                        {renderLoadConfiguration()}
                        {renderImageEditDialog()}
                        {renderProps.width !== 'xs' &&
                            showDesigner &&
                            is3DvisualMode &&
                            renderCloseDesignEditor()}
                        {customElements.main}
                    </>
                )}
                renderSidebar={renderProps => (
                    <CanvasStateProvider>
                        <TextEditorStateProvider>
                            <PopupArea>
                                {renderProps.width !== 'xs' && isPortraitMode ? (
                                    <TwoSideBottomBar
                                        leftSide={
                                            showDesigner && (
                                                <React.Suspense fallback={renderDesignerFallback()}>
                                                    {renderDesignerSelectionToolbox()}
                                                </React.Suspense>
                                            )
                                        }
                                        rightSide={
                                            <React.Fragment>
                                                {renderDesignAreaControlbox(renderProps)}
                                                {renderAmountPrice(props)}
                                            </React.Fragment>
                                        }
                                    />
                                ) : (
                                    <React.Fragment>
                                        {renderProps.width !== 'xs' ? (
                                            showDesigner ? (
                                                <React.Fragment>
                                                    {renderCloseGraphicsEditorButton(renderProps)}
                                                    {renderDesignAreaControlbox(renderProps)}
                                                </React.Fragment>
                                            ) : (
                                                <React.Fragment>
                                                    {showProductViewButton &&
                                                        renderCloseGraphicsEditorButton(renderProps)}
                                                    {renderEditDesignButton({ styledButton: false })}
                                                </React.Fragment>
                                            )
                                        ) : null}
                                        {showDesigner ? (
                                            <React.Suspense fallback={renderDesignerFallback()}>
                                                {renderDesignerSelectionToolbox()}
                                                {renderProps.width === 'xs' && (
                                                    <React.Fragment>
                                                        {renderAddVisualElement()}
                                                        {is3DvisualMode && renderCloseDesignEditor()}
                                                    </React.Fragment>
                                                )}
                                            </React.Suspense>
                                        ) : (
                                            renderProps.width === 'xs' &&
                                            props.activeDesignArea &&
                                            renderEditDesignButton({ styledButton: true })
                                        )}
                                        <div className={renderProps.classes.toBottom}>
                                            {renderProps.width !== 'xs'
                                                ? renderAmountPrice(props)
                                                : props.activeDesignArea
                                                ? renderCloseGraphicsEditorButton(renderProps)
                                                : renderAmountPrice(props)}
                                        </div>
                                    </React.Fragment>
                                )}
                            </PopupArea>
                        </TextEditorStateProvider>
                    </CanvasStateProvider>
                )}
                renderLoader={renderLoader}
                renderLicenseNotice={renderLicenseNotice}
                renderInvalidConfigurationNotice={renderInvalidConfigurationNotice}
            />
        </CanvasProvider>
    );
}

DesignerScreen.propTypes = {
    ...ScreenPropTypes,

    showProductViewButton: PropTypes.bool,
    showPreviewButton: PropTypes.bool,
    area: PropTypes.string,
    customElements: PropTypes.shape({
        main: PropTypes.node,
    }),

    // Render props
    renderDesignerSelectionToolbox: PropTypes.func,
    renderVisualizationEdit: PropTypes.func,
    renderDesignerFallback: PropTypes.func,

    renderHeader: PropTypes.func,
    renderDesignAreaControlbox: PropTypes.func,
    renderEditDesignButton: PropTypes.func,
    renderCloseGraphicsEditorButton: PropTypes.func,
    renderImageEditDialog: PropTypes.func,
    renderCloseDesignEditor: PropTypes.func,
    renderAddVisualElement: PropTypes.func,
    renderInvalidConfigurationNotice: PropTypes.func,

    // Components
    CanvasProvider: ReactComponentType.isRequired,
    CanvasStateProvider: ReactComponentType.isRequired,
    TextEditorStateProvider: ReactComponentType.isRequired,
    Layout: ReactComponentType.isRequired,
    PopupArea: ReactComponentType.isRequired,
    imageOnly: PropTypes.bool,
};

// eslint-disable-next-line react/prop-types
const renderDesignAreaControlbox = ({ area }) => <DesignAreaControlbox boxed={area === 'sidebar'} />;

// eslint-disable-next-line react/prop-types
const renderEditDesignButton = ({ styledButton }) => <EditDesignButton buttonXS={styledButton} />;

DesignerScreen.defaultProps = {
    // Render props
    renderCreator: () => null,
    renderDesigner: ({ designerClassName, visualizationOverlayMode } = {}) => {
        const designer = <Designer visualizationOverlayMode={visualizationOverlayMode} />;
        return (
            <React.Suspense fallback={<div>Loading Designer Component...</div>}>
                {visualizationOverlayMode ? (
                    <>
                        <DesignerClickAwayListener />
                        <div className={designerClassName}>{designer}</div>
                    </>
                ) : (
                    designer
                )}
            </React.Suspense>
        );
    },
    renderDesignerSelectionToolbox: () => (
        <React.Suspense fallback={<div>Loading Designer Toolbox...</div>}>
            <DesignerSelectionToolbox />
        </React.Suspense>
    ),
    renderHeader: () => <Header />,
    renderDesignerFallback: () => <div>Loading Designer Component...</div>,
    renderCloseGraphicsEditorButton: () => <CloseGraphicsEditorButton />,
    renderImageEditDialog: () => <ImageEditDialog />,
    renderCloseDesignEditor: () => <CloseDesignEditor />,
    renderAddVisualElement: () => <AddVisualElement autoHide />,
    renderEditDesignButton,
    renderDesignAreaControlbox,
    renderInvalidConfigurationNotice: () => <InvalidConfigurationNotice />,

    // Components
    CanvasProvider: DefaultCanvasProvider,
    CanvasStateProvider: DefaultCanvasStateProvider,
    TextEditorStateProvider: DefaultTextEditorStateProvider,
    Layout: DefaultLayout,
    PopupArea: DefaultPopupArea,
};
