import * as React from 'react';
import { useEffect } from 'react';

import { containerConnect } from 'Framework/ComponentContainer';

import { getCurrentVisualizationSettings, visualizationModeCheck } from 'App/Reducers/Configurator/Selectors';
import { isAnyDesignAreaSelected, isThereAFatalError } from 'App/Reducers/DesignArea/Selectors';
import * as uiActions from 'App/Reducers/UI/Actions';

import Error from '../../Shared/Containers/Error';
import ErrorPage from '../../Error/ProductionErrorPage';
import AlertMessages from 'App/Shared/Containers/AlertMessages';
import LandscapeInformation from './Components/LandscapeInformation';
import Confirm from './Containers/Confirm';
import SaveConfiguration from 'App/Shared/Containers/SaveConfiguration';
import SendEmail from 'App/Shared/Containers/SendEmail';
import PdfDownload from 'App/Shared/Containers/PdfDownload';
import LoadConfiguration from 'App/Shared/Containers/LoadConfiguration';
import DefaultFallbackVisualization from './Containers/FallbackVisualization';
import LicenseNotice from 'App/Shared/Containers/LicenseNotice';

import { DefaultVisualizationProvider } from '../../Modules/Visualization/DefaultVisualizationProvider';
import DefaultThemeProvider from './ThemeProvider';
import VisualizationContainer from './Containers/Visualization';
import FullScreenViewContainer from './Containers/FullScreenView';
import GlobalLoader from '../../Shared/Containers/GlobalLoader';
import AmountPrice from './Containers/AmountPrice';
import NoVisualization from './Components/NoVisualization/NoVisualization';
import {
    getConfigurationModeOptions,
    getSelectedConfigurationMode,
} from '../../Reducers/ConfigurationMode/Selectors';

import './Components/Styles.scss';
import ScreenPropTypes from './ScreenPropTypes';
import { getConf } from 'App/configuration';

import { DesignerScreen } from 'App/Modules/Designer/DesignerScreen';
import { CreatorScreen } from 'App/Modules/Creator/CreatorScreen';
import useMediaQuery from '@material-ui/core/useMediaQuery';
import { Services } from '../../ServiceLocator';
import { useParams } from 'react-router';

/**
 * Main Screen of the configurator
 */
export const Configurator = props => {
    const imageOnly = useMediaQuery(
        '(min-aspect-ratio: 13/9) and (min-height: 280px) and (max-width: 950px)'
    );
    useEffect(() => {
        if (imageOnly) {
            Services.visualization.enableDesignAreaInteraction(false);
        } else {
            Services.visualization.initDesignAreaInteraction();
        }
    }, [imageOnly]);

    let { identifier, code } = useParams();
    useEffect(() => {
        if ((identifier && identifier !== props.loadIdentifier) || (code && code !== props.loadCode)) {
            Services.configurator.initialize();
        }
    }, [identifier, code]);

    const { fatalError } = props;
    if (fatalError) {
        return <ErrorPage />;
    }
    const { children } = props;

    if (children instanceof Function) {
        return children(props);
    }

    const { selectedConfigurationMode, CreatorScreen, DesignerScreen } = props;
    const ScreenComponent =
        {
            creator: CreatorScreen,
            designer: DesignerScreen,
        }[selectedConfigurationMode] || (() => null);

    const { ThemeProvider, VisualizationProvider, customElements, renderLandscapeInformation } = props;

    return (
        <ThemeProvider>
            <VisualizationProvider>
                {renderLandscapeInformation()}
                <ScreenComponent imageOnly={imageOnly} {...props} />
                {customElements.root}
            </VisualizationProvider>
        </ThemeProvider>
    );
};

Configurator.propTypes = ScreenPropTypes;

// eslint-disable-next-line react/prop-types
const renderVisualization = ({ fullScreenViewProps }) => (
    <FullScreenViewContainer {...fullScreenViewProps}>
        <React.Suspense fallback={<div>Loading Visualization Component...</div>}>
            <VisualizationContainer BrokenComponent={NoVisualization} />
        </React.Suspense>
    </FullScreenViewContainer>
);

Configurator.defaultProps = {
    // Render props
    renderLandscapeInformation: () => <LandscapeInformation />,
    renderError: () => <Error />,
    renderAlertMessages: () => <AlertMessages />,
    renderConfirm: () => <Confirm />,
    renderSaveConfiguration: () => <SaveConfiguration />,
    renderLoadConfiguration: () => <LoadConfiguration />,
    renderSendEmail: () => <SendEmail />,
    renderPdfDownload: () => <PdfDownload />,
    renderLoader: () => <GlobalLoader />,
    renderAmountPrice: props => <AmountPrice {...props} />,
    renderLicenseNotice: props => <LicenseNotice {...props} />,
    renderVisualization,

    // Components
    DesignerScreen,
    CreatorScreen,
    VisualizationProvider: DefaultVisualizationProvider,
    FallbackVisualization: DefaultFallbackVisualization,
    ThemeProvider: DefaultThemeProvider,

    customElements: {},
    activeDesignArea: false,
    isPortraitMode: false,
};

const mapStateToProps = state => {
    const activeDesignArea = isAnyDesignAreaSelected(state);
    const fallbackMode = 'fallback' === getCurrentVisualizationSettings(state);
    const showDesigner = activeDesignArea && state.ui.visibilityMap.designer;
    const showProductViewButton = activeDesignArea;
    const fatalError = isThereAFatalError(state);
    const is3DvisualMode = visualizationModeCheck(state).is3D();
    const isPortraitMode = state.device.screen.orientation === 'portrait';
    const selectedConfigurationMode = getSelectedConfigurationMode(state);
    const showConfigurationModeSwitch = getConfigurationModeOptions(state).length > 0;

    const dock = getConf('dock');
    const vertical = dock ? dock === 'left' : state.device.screen.orientation === 'landscape';
    const showAddToCartButton = state.ui.visibilityMap.addToCartButton;
    const showConfigurationVariantSelection = state.ui.visibilityMap.configurationvariantSelection;
    const visualizationOverlayMode = visualizationModeCheck(state).is2DOverlay();
    const { loadIdentifier, loadCode } = state.configurator;

    const configuration = {
        showAddToCartButton: getConf('showAddToCartButton'),
        editCustomTitle: getConf('editCustomTitleBeforeSave'),
        showInitialOptionClassification: getConf('showInitialOptionclassification'),
        showStartHere: getConf('showStartHere'),
    };

    return {
        Component: Configurator,
        selectedConfigurationMode,
        showConfigurationModeSwitch,
        activeDesignArea,
        fallbackMode,
        showDesigner,
        showProductViewButton,
        is3DvisualMode,
        isPortraitMode,
        fatalError,
        vertical,
        showAddToCartButton,
        showConfigurationVariantSelection,
        configuration,
        visualizationOverlayMode,
        loadIdentifier,
        loadCode,
    };
};

const mapDispatchToProps = dispatch => ({
    dispatchAction: action => dispatch(action),
    setVisible: (name, show) => dispatch(uiActions.setVisible(name, show)),
});

export const ConnectedConfiguratorScreen = containerConnect(mapStateToProps, mapDispatchToProps);
