/**
 * Copyright (c) 2020, WSO2 Inc. (http://www.wso2.com). All Rights Reserved.
 *
 * This software is the property of WSO2 Inc. and its suppliers, if any.
 * Dissemination of any information or reproduction of any material contained
 * herein in any form is strictly forbidden, unless permitted by WSO2 expressly.
 * You may not alter or remove any copyright or other notice from copies of this content."
 */

import React, { FunctionComponent, ReactElement, useState, useEffect } from "react";
import { CodeEditor, GenericIcon } from "@wso2is/react-components";
import { Divider, Button, Message, Icon } from "semantic-ui-react";
import {
    ApplicationInterface,
    DocumentationConstants,
    SupportedAuthProtocolTypes,
    getInboundProtocolConfig
} from "../../../../../features/applications";
import {
    toggleHelpPanelVisibility
} from "../../../../../features/core";
import { useDispatch } from "react-redux";
import { useTranslation } from "react-i18next";
import { store } from "../../../../../features/core";
import { EncodeDecodeUtils } from "@wso2is/core/utils";
import { addAlert } from "@wso2is/core/store";
import { AlertLevels, TestableComponentInterface } from "@wso2is/core/models";
import { ReactComponent as AngularIcon } from "../../../../assets/images/icons/angular-icon.svg";
import { ReactComponent as ReactIcon } from "../../../../assets/images/icons/react-icon.svg";
import { ReactComponent as DownloadArrow } from "../../../../assets/images/icons/download-arrow.svg";
import DownloadIllustration from "../../../../assets/images/illustrations/download-sample-illustration.png";
import { SampleAppsEnum } from "../application-constants";

interface TryoutWebOIDCComponentProps extends TestableComponentInterface {
    application: ApplicationInterface;
}

/**
 * Tryout Component for Web OIDC Template.
 */
export const TryoutWebOIDCComponent: FunctionComponent<TryoutWebOIDCComponentProps> = (
    props: TryoutWebOIDCComponentProps
): ReactElement => {

    const {
        application,
        [ "data-testid" ]: testId
    } = props;

    const dispatch = useDispatch();
    const { t } = useTranslation();

    const deploymentConfigs = store.getState().config.deployment;
    const [ inboundProtocolConfigs, setInboundProtocolConfigs ] = useState(undefined);
    const [ authConfig, setAuthConfig ] = useState(undefined);
    const [ integrateCode, setIntegrateCode ] = useState("");
    const [ callBackURLNotSet, setCallbackURLNotSet ] = useState<boolean>(true);

    // TODO : Move get configs to util function
    useEffect(() => {
        if ( application === undefined ) {
            return;
        }

        let protocolConfigs: any = {};
        const selectedProtocolList: string[] = [];

        application?.inboundProtocols?.map((protocol) => {

            const protocolName = mapProtocolTypeToName(protocol.type);

            getInboundProtocolConfig(application.id, protocolName)
                .then((response) => {
                    protocolConfigs = {
                        ...protocolConfigs,
                        [protocolName]: response
                    };

                    selectedProtocolList.push(protocolName);
                })
                .catch((error) => {
                    if (error?.response?.status === 404) {
                        return;
                    }

                    if (error?.response && error?.response?.data && error?.response?.data?.description) {
                        dispatch(addAlert({
                            description: error.response?.data?.description,
                            level: AlertLevels.ERROR,
                            message: t("console:develop.features.applications.notifications.getInboundProtocolConfig" +
                                ".error.message")
                        }));

                        return;
                    }

                    dispatch(addAlert({
                        description: t("console:develop.features.applications.notifications.getInboundProtocolConfig" +
                            ".genericError.description"),
                        level: AlertLevels.ERROR,
                        message: t("console:develop.features.applications.notifications.getInboundProtocolConfig" +
                            ".genericError.message")
                    }));
                })
                .finally(() => {
                    setInboundProtocolConfigs(protocolConfigs);
                });
        });
    },  [ application ]);

    useEffect(() => {
        if (inboundProtocolConfigs == undefined) {
            return;
        }

        const urlArray = EncodeDecodeUtils.decodeURLRegex(inboundProtocolConfigs.oidc.callbackURLs[0]);

        if (urlArray && (urlArray.includes("http://localhost:5000") || urlArray.includes("https://localhost:5000") )) {
            setCallbackURLNotSet(false);
        }

        const configs = {
            clientHost: deploymentConfigs.clientHost,
            clientID: inboundProtocolConfigs.oidc.clientId,
            loginCallbackURL: "http://localhost:5000",
            logoutCallbackURL: "http://localhost:5000",
            serverOrigin: deploymentConfigs.serverOrigin,
            tenant: deploymentConfigs.tenant,
            tenantPath: deploymentConfigs.tenantPath
        };

        setAuthConfig(configs);
        setIntegrateCode(`{
    loginCallbackURL: "http://localhost:5000",
    logoutCallbackURL: "http://localhost:5000",,
    clientHost: "` + configs?.clientHost + `",
    clientID: "` + configs?.clientID + `",
    serverOrigin: "` + configs?.serverOrigin + `"
    tenant: "` + configs?.tenant + `",
    tenantPath: "` + configs?.tenantPath + `"
}
                            `);
    }, [ inboundProtocolConfigs ]);

    /**
     * Todo Remove this mapping and fix the backend.
     */
    const mapProtocolTypeToName = ((type: string): string => {
        let protocolName = type;
        if (protocolName === "oauth2") {
            protocolName = SupportedAuthProtocolTypes.OIDC;
        } else if (protocolName === "passivests") {
            protocolName = SupportedAuthProtocolTypes.WS_FEDERATION;
        } else if (protocolName === "wstrust") {
            protocolName = SupportedAuthProtocolTypes.WS_TRUST;
        } else if (protocolName === "samlsso") {
            protocolName = SupportedAuthProtocolTypes.SAML;
        }

        return protocolName;
    });

    const downloadConfigFile = (): void => {
        const blob = new Blob(
            [JSON.stringify(authConfig, null, 2)],
            { type: "application/json" }
        );
        const url = window.URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.style.display = "none";
        a.href = url;
        a.download = "config.json";
        document.body.appendChild(a);
        a.click();
        window.URL.revokeObjectURL(url);
    };

    return (
        <div className="quick-start-step-container">
            <div className="quick-start-step">
                <div className="step-content-container">
                    <h3 data-testid={ `${ testId }-download-sample-header` }>Download sample</h3>
                    <div className="step-content">
                        <p>Select the technology below to download</p>
                        <Button
                            data-testid={ `${ testId }-download-react-sample` }
                            className="sample-download"
                            basic
                            onClick={
                                () => window.open(DocumentationConstants.Samples_Catalog.get("JS_SPA_SAMPLE"),
                                    "") }
                        >
                            <GenericIcon
                                transparent
                                icon={ ReactIcon }
                                size="mini"
                                fill="default"
                                spaced="right"
                                floated="left"
                            />
                            Download { SampleAppsEnum.REACT } Sample
                            <GenericIcon
                                transparent
                                icon={ DownloadArrow }
                                size="mini"
                                fill="default"
                                spaced="left"
                                floated="right"
                            />
                        </Button>
                        <Button className="sample-download" basic>
                            <GenericIcon
                                transparent
                                icon={ AngularIcon }
                                size="mini"
                                fill="default"
                                spaced="right"
                                floated="left"
                            />
                            Download { SampleAppsEnum.ANGULAR } Sample
                            <GenericIcon
                                transparent
                                icon={ DownloadArrow }
                                size="mini"
                                fill="default"
                                spaced="left"
                                floated="right"
                            />
                        </Button>
                    </div>
                    <Divider hidden/>
                </div>
            </div>
            <div className="quick-start-step">
                <div className="step-content-container">
                    <h3 data-testid={ `${ testId }-configure-sample-header` }>Configure sample</h3>
                    <div className="step-content">
                        <p>Extract downloaded sample and replace the <strong>src/config.json</strong> file with the below configuration file</p>
                        { /* TODO : URL to be checked using a parameter */ }
                        { callBackURLNotSet &&
                        <Message warning>
                            <p>
                                In order to try out the sample, you need to add
                                <strong> https://localhost:5000</strong> to <strong>Redirect URLs</strong>
                                <Button color='orange' floated="right">Add Now</Button>
                            </p>
                        </Message>
                        }
                        <Button
                            onClick={ downloadConfigFile }
                            className="download-config"
                            size='small'
                            primary
                            data-testid={ `${ testId }-download-config` }
                        >
                            Download config.json
                        </Button>
                        <GenericIcon
                            icon={ DownloadIllustration }
                            size="large"
                            transparent
                            className="download-illustration"
                        />
                        <Divider hidden/>
                        <p>or copy and paste below configuration in <strong>src/config.json</strong>.</p>
                        <div className="code-segment">
                            <div className="action-buttons">
                                <Button basic size='tiny' className="copy-config" icon>
                                    <Icon name='copy' />
                                </Button>
                                <Button className="download-config" size='tiny' basic onClick={ () => {
                                    dispatch(toggleHelpPanelVisibility(true));
                                    // TODO: IMPORTANT Remove this once scroll is fixed.
                                    window.scrollTo(0,0);
                                } }>
                                    Configuration Help
                                </Button>
                            </div>
                            <CodeEditor
                                showLineNumbers={ false }
                                language="json"
                                sourceCode={ integrateCode }
                                options={ {
                                    gutters: []
                                } }
                                theme={ "light" }
                                readOnly={ true }
                            />
                        </div>
                    </div>
                    <Divider hidden/>
                </div>
            </div>
            <div className="quick-start-step">
                <div className="step-content-container">
                    <h3>Run</h3>
                    <div className="step-content">
                        <p>Run below command and visit: <a>http://localhost:5000</a></p>
                        <code>yarn start</code>
                    </div>
                    <Divider hidden/>
                </div>
            </div>
        </div>
    );
};
