/**
 * Copyright (c) 2021, 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 { TestableComponentInterface } from "@wso2is/core/models";
import { CodeEditor, Heading, Text } from "@wso2is/react-components";
import React, { FunctionComponent, ReactElement, ReactNode, useEffect, useState } from "react";
import { Divider, Icon } from "semantic-ui-react";
import {
    tomcatSAMLAgentLoginButtonAuthRequestCode,
    tomcatSAMLAgentLoginButtonCode,
    tomcatSAMLAgentLogoutCode,
    tomcatSAMLAgentMavenDependencyCode,
    tomcatSAMLAgentSamplePropertiesCode,
    tomcatSAMLAgentSampleWebXMLCode,
    wso2InternalRepoPointingCode
} from "./code-blocks";
import { SDKMeta } from "./meta";
import { SupportedTraditionalSAMLAppTechnologyTypes } from "./models";
import {
    ApplicationInterface,
    ApplicationTemplateInterface
} from "../../../../features/applications";
import { Config } from "../../../../features/core/configs";
import {
    VerticalStepper,
    VerticalStepperStepInterface
} from "../../../components/component-extensions/application/vertical-stepper";

interface IntegrateSDKsPropsInterface extends TestableComponentInterface {
    application: ApplicationInterface;
    technology: SupportedTraditionalSAMLAppTechnologyTypes;
    template: ApplicationTemplateInterface;
    inboundProtocolConfig: any;
}

/**
 * Integrate SDKs to Single Page Applications.
 *
 * @param {IntegrateSDKsPropsInterface} props - Props injected into the component.
 * @return {React.ReactElement}
 */
export const IntegrateSDKs: FunctionComponent<IntegrateSDKsPropsInterface> = (
    props: IntegrateSDKsPropsInterface
): ReactElement => {

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

    const [ SDKInitConfig, setSDKInitConfig ] = useState(undefined);

    useEffect(() => {
        if (!inboundProtocolConfig?.saml) {
            return;
        }

        const configs = {
            certificate: inboundProtocolConfig.certificate,
            issuer: inboundProtocolConfig.issuer,
            samlIssuer: inboundProtocolConfig.saml.issuer,
            serverOrigin: Config.getDeploymentConfig().serverHost,
            ssoUrl: inboundProtocolConfig.ssoUrl
        };

        setSDKInitConfig(configs);
    }, [ inboundProtocolConfig ]);

    const generateConfigureStepTitle = (technology: SupportedTraditionalSAMLAppTechnologyTypes): ReactNode => {

        if (technology === SupportedTraditionalSAMLAppTechnologyTypes.TOMCAT_SAML_AGENT) {
            return "Add Dependencies";
        }

        return "Configure Client";
    };

    const generateConfigureStep = (technology: SupportedTraditionalSAMLAppTechnologyTypes): ReactNode => {

        if (technology === SupportedTraditionalSAMLAppTechnologyTypes.TOMCAT_SAML_AGENT) {
            return (
                <>
                    <Text>
                        Starting with the <code className="inline-code">pom.xml</code>,
                        the following dependencies should be added for the web app to be using the SAML SDK.
                    </Text>

                    <div className="code-segment">
                        <CodeEditor
                            readOnly
                            showLineNumbers
                            withClipboardCopy
                            height="100%"
                            language="htmlmixed"
                            sourceCode={ tomcatSAMLAgentMavenDependencyCode() }
                            options={ {
                                lineWrapping: true
                            } }
                            theme="dark"
                        />
                    </div>

                    <Divider hidden />

                    <Text>
                        The SDK is hosted at the <strong>WSO2 Internal Repository</strong>.
                        Point to the repository as follows.
                    </Text>

                    <div className="code-segment">
                        <CodeEditor
                            readOnly
                            showLineNumbers
                            withClipboardCopy
                            language="htmlmixed"
                            sourceCode={ wso2InternalRepoPointingCode() }
                            options={ {
                                lineWrapping: true
                            } }
                            theme="dark"
                        />
                    </div>

                    <div className="mt-3">
                        <p>
                            Check out the <a
                            href={ SDKMeta.tomcatSAMLAgent.readme }
                            target="_blank"
                            rel="noopener noreferrer"
                            className="link external"
                        >
                            <Icon name="github" />documentation
                        </a> to learn more.
                        </p>
                    </div>
                </>
            );
        }

        return null;
    };

    const generateInitialisationStepTitle = (technology: SupportedTraditionalSAMLAppTechnologyTypes): ReactNode => {

        if (technology === SupportedTraditionalSAMLAppTechnologyTypes.TOMCAT_SAML_AGENT) {
            return "Configure";
        }

        return "Configure";
    };

    const generateInitialisationStep = (technology: SupportedTraditionalSAMLAppTechnologyTypes): ReactNode => {

        if (technology === SupportedTraditionalSAMLAppTechnologyTypes.TOMCAT_SAML_AGENT) {

            return (
                <>
                    <Text>
                        Before the <code className="inline-code">web.xml</code> configurations,
                        we will look at adding the resources files. In the sample-app, create a file named
                        <code className="inline-code">sample-app.properties</code> in the <code
                        className="inline-code">&#60;APP_HOME&#62;/resources</code> directory. The
                        <code className="inline-code">sample-app.properties</code> file contains properties
                        similar to the following:
                    </Text>

                    <div className="code-segment">
                        <CodeEditor
                            readOnly
                            showLineNumbers
                            withClipboardCopy
                            language="htmlmixed"
                            sourceCode={ tomcatSAMLAgentSamplePropertiesCode(SDKInitConfig) }
                            options={ {
                                lineWrapping: true
                            } }
                            theme="dark"
                        />
                    </div>

                    <Divider hidden />

                    <Text>
                        Next, generate keystore file and copy it to the <code className="inline-code">
                        &#60;APP_HOME&#62;/resources</code> directory. For simplicity, we are using the
                        <code className="inline-code">wso2carbon.jks</code> keystore file of the <strong>
                        { }</strong> which resides in <code className="inline-code">
                        &#60;APP_HOME&#62;/repository/resources/security/</code> directory. You may need to
                        update the following properties of <code className="inline-code">
                        &#60;APP_HOME&#62;/WEB-INF/web.xml</code> file if you are using different keystore than
                        <code className="inline-code">wso2carbon.jks</code>.
                    </Text>

                    <Text>
                        Finally, copy and paste the following configurations to the
                        <code className="inline-code">&#60;APP_HOME&#62;/WEB-INF/web.xml</code> file.
                    </Text>

                    <div className="code-segment">
                        <CodeEditor
                            readOnly
                            showLineNumbers
                            withClipboardCopy
                            language="htmlmixed"
                            sourceCode={ tomcatSAMLAgentSampleWebXMLCode() }
                            options={ {
                                lineWrapping: true
                            } }
                            theme="dark"
                        />
                    </div>
                </>
            );
        }

        return null;
    };

    const generateAuthenticationStep = (technology: SupportedTraditionalSAMLAppTechnologyTypes): ReactNode => {

        if (technology === SupportedTraditionalSAMLAppTechnologyTypes.TOMCAT_SAML_AGENT) {

            return (
                <>
                    <Text>
                        The web app itself has two pages, <code className="inline-code">index.html</code> and
                        <code className="inline-code">home.jsp</code>, and a <code className="inline-code">web.xml
                    </code> file. The <code className="inline-code">index.html</code> contains a login button which
                        we would use to forward the user to the secured page.
                    </Text>

                    <div className="code-segment">
                        <CodeEditor
                            readOnly
                            showLineNumbers
                            withClipboardCopy
                            language="htmlmixed"
                            sourceCode={ tomcatSAMLAgentLoginButtonCode() }
                            options={ {
                                lineWrapping: true
                            } }
                            height="100%"
                            theme="dark"
                        />
                    </div>

                    <Divider hidden />

                    <Text>
                        Now we need to update the form action to trigger a SAML authentication request as follows.
                    </Text>

                    <div className="code-segment">
                        <CodeEditor
                            readOnly
                            showLineNumbers
                            withClipboardCopy
                            language="htmlmixed"
                            sourceCode={ tomcatSAMLAgentLoginButtonAuthRequestCode() }
                            options={ {
                                lineWrapping: true
                            } }
                            height="100%"
                            theme="dark"
                        />
                    </div>

                    <Divider hidden />

                    <Text>
                        The home.jsp page is a page which we want to secure i.e. in case there are no active sessions,
                        the <a>http://localhost.com:8080/sample-app/home.jsp</a> should not be accessible.
                        In the sample we are using, if there is no active session in place, we would redirect the user
                        for authentication. In the home.jsp, there is a logout link which will be used to create a
                        SLO request.
                    </Text>

                    <div className="code-segment">
                        <CodeEditor
                            readOnly
                            oneLiner
                            withClipboardCopy
                            language="htmlmixed"
                            sourceCode={ tomcatSAMLAgentLogoutCode() }
                            theme="dark"
                        />
                    </div>
                </>
            );
        }

        return null;
    };

    const integrationFlowSteps: VerticalStepperStepInterface[] = [
        {
            stepContent: generateConfigureStep(technology),
            stepTitle: generateConfigureStepTitle(technology)
        },
        {
            stepContent: generateInitialisationStep(technology),
            stepTitle: generateInitialisationStepTitle(technology)
        },
        {
            stepContent: generateAuthenticationStep(technology),
            stepTitle: "Add Login"
        }
    ];

    const renderPrerequisitesStep = (): ReactElement => {

        return (
            <div className="mt-3 mb-6">
                <Heading as="h3">Prerequisite</Heading>
                <Text>
                    You will need to have <strong>Apache Maven 3.6.x or higher</strong> installed on
                    your environment to try out the integration.
                </Text>
                <Text>To download <strong>Apache Maven</strong>, navigate to the official <a
                    href="https://maven.apache.org/download.cgi"
                    target="_blank"
                    rel="noopener noreferrer"
                    className="link external"
                >downloads</a> page.
                </Text>
            </div>
        );
    };

    return (
        <>
            { renderPrerequisitesStep() }
            <VerticalStepper
                alwaysOpen
                isSidePanelOpen
                stepContent={ integrationFlowSteps }
                isNextEnabled={ technology !== undefined }
                data-testid={ `${ testId }-vertical-stepper` }
            />
        </>
    );
};
