import { setSecuredSupport } from '@rh-support/api';
import get from 'lodash/get';
import includes from 'lodash/includes';
import isEmpty from 'lodash/isEmpty';
import isFunction from 'lodash/isFunction';
import map from 'lodash/map';
import React, { Suspense, useContext, useEffect, useRef } from 'react';
import { Route, RouteComponentProps } from 'react-router-dom';
import { AppMetadataStateContext } from '../../context/AppMetadataContext';
import { CreateCaseStateContext } from '../../context/CreateCaseContext';
import { RouteContext, RouteDispatchContext } from '../../context/RouteContext';
import { usePrevious } from '../../hooks/usePrevious';
import { AppRouteSections, IRouteUrlParams, RouteReducerConstants } from '../../reducers/RouteReducer';
import CaseUtils from '../../utils/caseUtils';
import RouteUtils from '../../utils/routeUtils';
import LoadingIndicator from '../shared/LoadingIndicator';
import Suggestions from '../Suggestions/Suggestions';
import MainSection from './MainSection';

interface IProps {
    routeProps: RouteComponentProps<IRouteUrlParams>;
}
const defaultProps: Partial<IProps> = {};
const ProductSelector = React.lazy(() => import(/* webpackChunkName: 'ProductSelector' */  '../ProductSelector/ProductSelector'));
const Issue = React.lazy(() => import(/* webpackChunkName: 'Suggestions' */  '../Issue/Issue'));
const Results = React.lazy(() => import(/* webpackChunkName: 'Results' */  '../Results/Results'));
const OpenCase = React.lazy(() => import(/* webpackChunkName: 'OpenCase' */ '../OpenCase/OpenCase'));
const ImproveCase = React.lazy(() => import(/* webpackChunkName: 'ImproveCase' */ '../ImproveCase/ImproveCase'));
const CaseManagement = React.lazy(() => import(/* webpackChunkName: 'CaseManagement' */ '../CaseManagement/CaseManagement'));
const Review = React.lazy(() => import(/* webpackChunkName: 'Review' */ '../Review/Review'));
const SubmitCase = React.lazy(() => import(/* webpackChunkName: 'SubmitCase' */  '../SubmitCase/SubmitCase'));

export default function WizardMain(props: IProps) {
    const allSectionRefs = {
        [AppRouteSections.PRODUCT_SELECTOR]: useRef<HTMLDivElement>(null),
        [AppRouteSections.SUGGESTIONS]: useRef<HTMLDivElement>(null),
        [AppRouteSections.ISSUE]: useRef<HTMLDivElement>(null),
        [AppRouteSections.RESULTS]: useRef<HTMLDivElement>(null),
        [AppRouteSections.OPEN_CASE]: useRef<HTMLDivElement>(null),
        [AppRouteSections.IMPROVE_CASE]: useRef<HTMLDivElement>(null),
        [AppRouteSections.CASE_MGM]: useRef<HTMLDivElement>(null),
        [AppRouteSections.REVIEW]: useRef<HTMLDivElement>(null),
        [AppRouteSections.SUBMIT_CASE]: useRef<any>(null)
    };
    const dispatchToRouteReducer = useContext(RouteDispatchContext);
    const { routeState: { activeSection, appRouteSectionsSequence, appRouteConfugurations, sectionsToHide } } = useContext(RouteContext);
    const { appMetadataState: {
        loggedInUsersAccount,
    } } = useContext(AppMetadataStateContext);
    const { createCaseState: {isCreatingCase} } = useContext(CreateCaseStateContext);
    const prevActiveSection = usePrevious(activeSection);

    // GS4 Related
    // 1. Setting securedSupport in env.ts
    useEffect(() => {
        if (isEmpty(loggedInUsersAccount.data)) { return; }
        setSecuredSupport(loggedInUsersAccount.data.is_secured_support);
    }, [loggedInUsersAccount]);

    // Default page related
    useEffect(() => {
        const activeSectionLocal = RouteUtils.getActiveSection(props.routeProps, appRouteSectionsSequence);
        if (isEmpty(activeSectionLocal) || (activeSectionLocal !== AppRouteSections.PRODUCT_SELECTOR)) {
            RouteUtils.navigateToSection(props.routeProps, AppRouteSections.PRODUCT_SELECTOR, appRouteSectionsSequence);
        }
    }, []);
    // Hidden Section Related
    useEffect(() => {
        if (includes(sectionsToHide, activeSection)) {
            RouteUtils.navigateToSection(props.routeProps, appRouteConfugurations[activeSection].nextSection, appRouteSectionsSequence);
        }
    }, [sectionsToHide, activeSection, props.routeProps, appRouteSectionsSequence]);
    // Navigation related
    useEffect(() => {
        const activeSectionLocal = RouteUtils.getActiveSection(props.routeProps, appRouteSectionsSequence);
        if (isEmpty(activeSectionLocal) || props.routeProps.location.pathname === '/') {
            props.routeProps.history.replace({ pathname: `/${AppRouteSections.PRODUCT_SELECTOR}` });
        } else {
            dispatchToRouteReducer({ type: RouteReducerConstants.activeSectionChanged, payload: { activeSection: activeSectionLocal } });
        }
    }, [props.routeProps]);
    // scrolling and focus related
    useEffect(() => {
        if (!isEmpty(activeSection) && prevActiveSection !== activeSection && isFunction(get(allSectionRefs[activeSection], 'current.scrollIntoView'))) {
            CaseUtils.scrollIntoSection(allSectionRefs[activeSection]);
            allSectionRefs[activeSection].current.focus();
        }
    }, [activeSection, allSectionRefs]);

    const renderProductSelectorPage = () => {
        return (
            <MainSection ref={allSectionRefs[AppRouteSections.PRODUCT_SELECTOR]}
                section={AppRouteSections.PRODUCT_SELECTOR}
                activeSection={activeSection}
                title={appRouteConfugurations[AppRouteSections.PRODUCT_SELECTOR].title}
                description="Select which product and version is experiencing the issue.">
                <Suspense fallback={<LoadingIndicator size="sm" />}>
                    <ProductSelector routeProps={props.routeProps}/>
                </Suspense>
            </MainSection>
        );
    };

    const renderSuggestionsPage = () => {
        return (
            <Suggestions
                ref={allSectionRefs[AppRouteSections.SUGGESTIONS]}
                sectionRef={allSectionRefs[AppRouteSections.SUGGESTIONS]}
                routeProps={props.routeProps}
                id={AppRouteSections.SUGGESTIONS}
                className={`wizard-main-section${activeSection === AppRouteSections.SUGGESTIONS ? ' wizard-main-active-section' : ''}`}
            />
        );
    };

    const renderIssuePage = () => {
        return (
            <MainSection ref={allSectionRefs[AppRouteSections.ISSUE]}
                section={AppRouteSections.ISSUE}
                activeSection={activeSection}
                title={appRouteConfugurations[AppRouteSections.ISSUE].title}>
                <Suspense fallback={<LoadingIndicator size="sm" />}>
                    <Issue routeProps={props.routeProps}/>
                </Suspense>
            </MainSection>
        );
    };

    const renderResultsPage = () => {
        return (
            <MainSection ref={allSectionRefs[AppRouteSections.RESULTS]}
                section={AppRouteSections.RESULTS}
                activeSection={activeSection}
                title={appRouteConfugurations[AppRouteSections.RESULTS].title}>
                <Suspense fallback={<LoadingIndicator size="sm" />}>
                    <Results />
                </Suspense>
            </MainSection>
        );
    };

    const renderOpenCasePage = () => {
        return (
            <MainSection ref={allSectionRefs[AppRouteSections.OPEN_CASE]}
                section={AppRouteSections.OPEN_CASE}
                activeSection={activeSection}
                title={<>
                    {appRouteConfugurations[AppRouteSections.OPEN_CASE].title}
                    {loggedInUsersAccount.data.is_secured_support && <span className="secured-support">Secured Support</span>}
                </>}>
                <Suspense fallback={<LoadingIndicator size="sm" />}>
                    <OpenCase />
                </Suspense>
            </MainSection>
        );
    };

    const renderImproveCasePage = () => {
        return (
            <MainSection ref={allSectionRefs[AppRouteSections.IMPROVE_CASE]}
                section={AppRouteSections.IMPROVE_CASE}
                activeSection={activeSection}
                title={appRouteConfugurations[AppRouteSections.IMPROVE_CASE].title}
                description="All fields optional"
                descriptionClassName="text-medium-grey">
                <Suspense fallback={<LoadingIndicator size="sm" />}>
                    <ImproveCase />
                </Suspense>
            </MainSection>
        );
    };

    const renderCaseManagementPage = () => {
        return (
            <MainSection ref={allSectionRefs[AppRouteSections.CASE_MGM]}
                section={AppRouteSections.CASE_MGM}
                activeSection={activeSection}
                title={appRouteConfugurations[AppRouteSections.CASE_MGM].title}
                description="All fields optional"
                descriptionClassName="text-medium-grey">
                <Suspense fallback={<LoadingIndicator size="sm" />}>
                    <CaseManagement />
                </Suspense>
            </MainSection>
        );
    };

    const renderReview = () => {
        return (
            <MainSection ref={allSectionRefs[AppRouteSections.REVIEW]}
                section={AppRouteSections.REVIEW}
                activeSection={activeSection}
                title={appRouteConfugurations[AppRouteSections.REVIEW].title}>
                <Suspense fallback={<LoadingIndicator size="sm" />}>
                    <Review routeProps={props.routeProps}/>
                </Suspense>
            </MainSection>
        );
    };

    const renderSubmitCasePage = () => {
        return (
            <MainSection ref={allSectionRefs[AppRouteSections.SUBMIT_CASE]}
                section={AppRouteSections.SUBMIT_CASE}
                activeSection={activeSection}
                title={appRouteConfugurations[AppRouteSections.SUBMIT_CASE].title}
                isLoading={isCreatingCase}>
                <Suspense fallback={<LoadingIndicator size="sm" />}>
                    <SubmitCase routeProps={props.routeProps}/>
                </Suspense>
            </MainSection>
        );
    };

    // const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {
    //     const hasReachedBottom = e.currentTarget.scrollHeight - e.currentTarget.scrollTop === e.currentTarget.clientHeight;
    //     if (hasReachedBottom) {
    //         // tslint:disable-next-line:no-console
    //         console.log('Reached Bottom');
    //         if (isSectionValid) {
    //             // tslint:disable-next-line:no-console
    //             console.log('will load next section');
    //             // RouteUtils.navigateToSection(props.routeProps, nextSection);
    //         }
    //     }
    // };
    const mainSectionComponents = {
        [AppRouteSections.PRODUCT_SELECTOR]: renderProductSelectorPage,
        [AppRouteSections.SUGGESTIONS]: renderSuggestionsPage,
        [AppRouteSections.ISSUE]: renderIssuePage,
        [AppRouteSections.RESULTS]: renderResultsPage,
        [AppRouteSections.OPEN_CASE]: renderOpenCasePage,
        [AppRouteSections.IMPROVE_CASE]: renderImproveCasePage,
        [AppRouteSections.CASE_MGM]: renderCaseManagementPage,
        [AppRouteSections.REVIEW]: renderReview,
        [AppRouteSections.SUBMIT_CASE]: renderSubmitCasePage
    };
    return (
        <main id="wizard-main">
            <Route
                exact={true}
                path="/"
                render={mainSectionComponents[AppRouteSections.PRODUCT_SELECTOR]}
            />
            {map(appRouteSectionsSequence, (activeSectionLocal) => {
                if (activeSectionLocal === AppRouteSections.SUBMIT_CASE) { return; }
                return (<Route
                    key={`route-${activeSectionLocal}`}
                    exact={false}
                    path={`${RouteUtils.getRoutePathForActiveSection(activeSectionLocal, appRouteSectionsSequence)}`}
                    render={mainSectionComponents[activeSectionLocal]}
                />);
            })}
            <Route
                exact={false}
                ref={allSectionRefs[AppRouteSections.SUBMIT_CASE]}
                path={`/${AppRouteSections.SUBMIT_CASE}`}
                render={mainSectionComponents[AppRouteSections.SUBMIT_CASE]}
            />
        </main>
    );
}
WizardMain.defaultProps = defaultProps;
