import React from 'react';
import { Trans } from '@lingui/react';
import { Errors } from '../../validation/errors/types';
import {
    noInternet,
    locationOff,
    locationTimeout,
    serverError,
    arrivalAdvisorGlyphLogo,
    noMatchingSearchResults,
    invalidSearchLocation,
} from '../../application/images';
import { ErrorScreenComponent } from './error_screen_component';
import { AppSettingsButtonComponent, SettingsType } from '../app_settings_button_component';
import { isAndroid } from '../../application/helpers/is_android';
import { View, Text } from 'native-base';
import { textStyles, bulletPoint } from '../../application/styles';
import { RegionCode } from '../../validation/region/types';
import { useRegion } from '../main/context_component';
import { UxTheme } from '../../application/ux_themes';

type ErrorScreenSwitcherComponentProps = {
    readonly errorType: Errors;
    readonly refreshScreen: () => void;
    readonly header?: JSX.Element;
    readonly theme: UxTheme;
};

export const ErrorScreenSwitcherComponent = (props: ErrorScreenSwitcherComponentProps): JSX.Element => {
    const sharedProps = {
        refreshScreen: props.refreshScreen,
        header: props.header,
    };
    const region = useRegion();
    switch (props.errorType) {
        case Errors.Offline:
            return (
                <ErrorScreenComponent
                    imageSource={noInternet}
                    title={<Trans>Can't reach the internet</Trans>}
                    subTitle={getSubTitleForError(Errors.Offline)}
                    {...sharedProps}
                />
            );
        case Errors.NoLocationPermission:
            return (
                <ErrorScreenComponent
                    imageSource={locationOff}
                    title={<Trans>Enable location services</Trans>}
                    subTitle={getSubTitleForError(Errors.NoLocationPermission)}
                    additionalContent={getAdditionalContentForError(Errors.NoLocationPermission, region, props.theme)}
                    {...sharedProps}
                />
            );
        case Errors.LocationFetchTimeout:
            return (
                <ErrorScreenComponent
                    imageSource={locationTimeout}
                    title={<Trans>Check location services</Trans>}
                    subTitle={getSubTitleForError(Errors.LocationFetchTimeout)}
                    additionalContent={getAdditionalContentForError(Errors.LocationFetchTimeout, region, props.theme)}
                    {...sharedProps}
                />
            );
        case Errors.InvalidServerData:
        case Errors.BadServerResponse:
            return (
                <ErrorScreenComponent
                    imageSource={serverError}
                    title={<Trans>Server error</Trans>}
                    subTitle={getSubTitleForError(Errors.BadServerResponse)}
                    {...sharedProps}
                />
            );
        case Errors.NoMatchingSearchResults:
            return (
                <ErrorScreenComponent
                    imageSource={noMatchingSearchResults}
                    title={<Trans>No results found. Try to:</Trans>}
                    additionalContent={getAdditionalContentForError(Errors.NoMatchingSearchResults, region, props.theme)}
                    {...sharedProps}
                />
            );
        case Errors.InvalidSearchLocation:
            return (
                <ErrorScreenComponent
                    imageSource={invalidSearchLocation}
                    title={<Trans>Invalid location. Try:</Trans>}
                    additionalContent={getAdditionalContentForError(Errors.InvalidSearchLocation, region, props.theme)}
                    {...sharedProps}
                />
            );
        default:
        case Errors.Exception:
            return (
                <ErrorScreenComponent
                    imageSource={arrivalAdvisorGlyphLogo}
                    title={<Trans>An error occurred</Trans>}
                    {...sharedProps}
                />
            );
    }
};

const getSubTitleForError = (error: Errors): JSX.Element | undefined => {
    switch (error) {
        case Errors.Offline:
            return (
                <Trans>
                    Services are not available offline.
                    Please connect to the internet and try again.
                </Trans>
            );
        case Errors.NoLocationPermission:
            return (
                <Trans>
                    To find services, please turn on Location Services
                    for Arrival Advisor in Settings and try again.
                </Trans>
            );
        case Errors.LocationFetchTimeout:
            return isAndroid() ?
                <Trans>
                    It took too long finding your location.
                    Setting your device's Location Services to “High Accuracy” can sometimes fix this problem.
                </Trans>
                :
                <Trans>It took too long finding your location.</Trans>;
        case Errors.InvalidServerData:
        case Errors.BadServerResponse:
            return (
                <Trans>
                    We’re having difficulty connecting to the server.
                    Please try again later.
                </Trans>
            );
        default:
            return undefined;
    }
};

const getAdditionalContentForError = (error: Errors, region: RegionCode, theme: UxTheme): JSX.Element | undefined => {
    switch (error) {
        case (Errors.NoLocationPermission):
            return isAndroid() ?
                <AppSettingsButtonComponent settingsType={SettingsType.AndroidAppSettings} theme={theme} />
                :
                <AppSettingsButtonComponent settingsType={SettingsType.IOSAppSettings} theme={theme} />;
        case (Errors.LocationFetchTimeout):
            return isAndroid() ?
                <AppSettingsButtonComponent settingsType={SettingsType.AndroidAppLocation} theme={theme} />
                :
                undefined;
        case (Errors.NoMatchingSearchResults):
            return renderNoMatchingResultsSuggestions();
        case (Errors.InvalidSearchLocation):
            return renderInvalidSearchLocationSuggestions(region);
        default:
            return undefined;
    }
};

const renderNoMatchingResultsSuggestions = (): JSX.Element => (
    <View>
        <Text style={textStyles.paragraphStyleBrown}>
            {bulletPoint} <Trans>Ensure your search is in English</Trans>
        </Text>
        <Text style={textStyles.paragraphStyleBrown}>
            {bulletPoint} <Trans>Double check for spelling</Trans>
        </Text>
        <Text style={textStyles.paragraphStyleBrown}>
            {bulletPoint} <Trans>Search for a different keyword</Trans>
        </Text>
    </View>
);

const renderInvalidSearchLocationSuggestions = (region: RegionCode): JSX.Element => {
    const city = getCity(region);
    const street = getStreet(region);
    const postalCode = getPostalCode(region);
    return <View>
        <Text style={textStyles.paragraphStyleBrown}>
            {bulletPoint} <Trans>My location</Trans>
        </Text>
        <Text style={textStyles.paragraphStyleBrown}>
            {bulletPoint} <Trans>City - "{city}"</Trans>
        </Text>
        <Text style={textStyles.paragraphStyleBrown}>
            {bulletPoint} <Trans>Street - "{street}"</Trans>
        </Text>
        <Text style={textStyles.paragraphStyleBrown}>
            {bulletPoint} <Trans>Postal Code - "{postalCode}"</Trans>
        </Text>
    </View>;
};

const getStreet = (region: RegionCode): string => {
    if (region === RegionCode.MB) {
        return '271 Portage Ave Winnipeg';
    }
    return '1356 Kingsway Vancouver';
};

const getCity = (region: RegionCode): string => {
    if (region === RegionCode.MB) {
        return 'Winnipeg';
    }
    return 'Vancouver';
};

const getPostalCode = (region: RegionCode): string => {
    if (region === RegionCode.MB) {
        return 'R3B 2A8';
    }
    return 'V5Y 1V4';
};