<%--
~ Copyright (c) 2021, WSO2 LLC. (https://www.wso2.com). All Rights Reserved.
~
~ This software is the property of WSO2 LLC. 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.
--%>

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%@ page import="org.apache.commons.collections.CollectionUtils" %>
<%@ page import="org.apache.commons.collections.MapUtils" %>
<%@ page import="org.apache.commons.lang.ArrayUtils" %>
<%@ page import="org.apache.commons.lang.StringUtils" %>
<%@ page import="org.apache.commons.text.StringEscapeUtils" %>
<%@ page import="org.owasp.encoder.Encode" %>
<%@ page import="org.wso2.carbon.identity.application.authentication.endpoint.util.AuthenticationEndpointUtil" %>
<%@ page import="static org.wso2.carbon.identity.application.authentication.endpoint.util.Constants.STATUS" %>
<%@ page import="static org.wso2.carbon.identity.application.authentication.endpoint.util.Constants.STATUS_MSG" %>
<%@ page import="org.wso2.carbon.identity.application.authentication.endpoint.util.Constants" %>
<%@ page import="org.wso2.carbon.identity.captcha.util.CaptchaUtil" %>
<%@ page import="org.wso2.carbon.identity.core.URLBuilderException" %>
<%@ page import="org.wso2.carbon.identity.mgt.constants.SelfRegistrationStatusCodes" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.IdentityManagementEndpointConstants" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.IdentityManagementServiceUtil" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.IdentityManagementEndpointUtil" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.client.ApiException" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.client.api.ReCaptchaApi" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.client.model.ReCaptchaProperties" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.client.SelfRegistrationMgtClient" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.client.SelfRegistrationMgtClientException" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.client.ApplicationDataRetrievalClient" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.client.ApplicationDataRetrievalClientException" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.client.ConfiguredAuthenticatorsRetrievalClient" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.client.ConfiguredAuthenticatorsRetrievalClientException" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.client.IdentityProviderDataRetrievalClient" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.client.IdentityProviderDataRetrievalClientException" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.client.api.UsernameRecoveryApi" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.client.model.Claim" %>
<%@ page import="org.wso2.carbon.identity.mgt.endpoint.util.client.model.User" %>
<%@ page import="org.wso2.carbon.identity.core.util.IdentityTenantUtil" %>
<%@ page import="org.wso2.carbon.identity.core.ServiceURLBuilder" %>
<%@ page import="org.wso2.carbon.utils.multitenancy.MultitenantUtils" %>
<%@ page import="java.io.File" %>
<%@ page import="java.util.Arrays" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.Locale" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.TreeMap" %>
<%@ page import="java.util.Enumeration" %>
<%@ page import="org.json.JSONObject" %>
<%@ page import="org.json.JSONArray" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="layout" uri="org.wso2.identity.apps.taglibs.layout.controller" %>

<jsp:directive.include file="includes/localize.jsp"/>
<jsp:directive.include file="tenant-resolve.jsp"/>
<%-- Branding Preferences --%>
<jsp:directive.include file="extensions/branding-preferences.jsp"/>

<%
    String BASIC_AUTHENTICATOR = "BasicAuthenticator";
    String OPEN_ID_AUTHENTICATOR = "OpenIDAuthenticator";
    String GOOGLE_AUTHENTICATOR = "GoogleOIDCAuthenticator";
    String GITHUB_AUTHENTICATOR = "GithubAuthenticator";
    String FACEBOOK_AUTHENTICATOR = "FacebookAuthenticator";
    String OIDC_AUTHENTICATOR = "OpenIDConnectAuthenticator";
    String commonauthURL = "../commonauth";

    boolean error = IdentityManagementEndpointUtil.getBooleanValue(request.getAttribute("error"));
    boolean isSaaSApp = Boolean.parseBoolean(request.getParameter("isSaaSApp"));
    boolean skipSignUpEnableCheck = Boolean.parseBoolean(request.getParameter("skipsignupenablecheck"));
    boolean allowchangeusername = Boolean.parseBoolean(request.getParameter("allowchangeusername"));
    boolean isPasswordProvisionEnabled = Boolean.parseBoolean(request.getParameter("passwordProvisionEnabled"));
    boolean piisConfigured = false;

    String callback = Encode.forHtmlAttribute(request.getParameter("callback"));
    String backToUrl = callback;
    String sp = Encode.forHtmlAttribute(request.getParameter("sp"));
    String previousStep = Encode.forHtmlAttribute(request.getParameter("previous_step"));
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    String emailValue = request.getParameter("username");
    String errorCode = null;
    String spId = "";
    String errorCodeFromRequest = IdentityManagementEndpointUtil.getStringValue(request.getAttribute("errorCode"));
    String errorMsg = IdentityManagementEndpointUtil.getStringValue(request.getAttribute("errorMsg"));
    String consentPurposeGroupName = "SELF-SIGNUP";
    String consentPurposeGroupType = "SYSTEM";

    String[] missingClaimList = new String[0];
    String[] missingClaimDisplayName = new String[0];
    Integer defaultPurposeCatId = null;

    Object errorCodeObj = request.getAttribute("errorCode");
    Object errorMsgObj = request.getAttribute("errorMsg");
    JSONObject usernameValidityResponse;

    Map<String, Claim> uniquePIIs = null;

    SelfRegistrationMgtClient selfRegistrationMgtClient = new SelfRegistrationMgtClient();
    User user = IdentityManagementServiceUtil.getInstance().resolveUser(username, tenantDomain, isSaaSApp);

    ApplicationDataRetrievalClient applicationDataRetrievalClient = new ApplicationDataRetrievalClient();
    try {
        // Retrieve application Id.
        spId = applicationDataRetrievalClient.getApplicationID(tenantDomain,sp);
    } catch (Exception e) {
        // Nothing happens.
    }

    // Get authenticators configured for an application.
    JSONArray configuredAuthenticators = null;
    if (!StringUtils.equalsIgnoreCase(spId,"")) {
        try {
            ConfiguredAuthenticatorsRetrievalClient configuredAuthenticatorsRetrievalClient = new ConfiguredAuthenticatorsRetrievalClient();
            configuredAuthenticators = configuredAuthenticatorsRetrievalClient.getConfiguredAuthenticators(spId);
        } catch (Exception e) {
            configuredAuthenticators = null;
        }
    }

    String identityServerEndpointContextParam = application.getInitParameter("IdentityServerEndpointContextURL");
    if (!StringUtils.equals(tenantDomain, "carbon.super")) {
        identityServerEndpointContextParam = ServiceURLBuilder.create().setTenant(tenantDomain).build()
                .getAbsolutePublicURL();
    }
    commonauthURL = identityServerEndpointContextParam + "/commonauth";

    String multiOptionURIParam = "";
    String baseURL;
    try {
        baseURL = ServiceURLBuilder.create().addPath(request.getRequestURI()).build().getRelativePublicURL();
    } catch (URLBuilderException e) {
        request.setAttribute(STATUS, AuthenticationEndpointUtil.i18n(recoveryResourceBundle, "internal.error.occurred"));
        request.setAttribute(STATUS_MSG, AuthenticationEndpointUtil.i18n(recoveryResourceBundle, "error.when.processing.authentication.request"));
        request.getRequestDispatcher("error.do").forward(request, response);
        return;
    }

    String queryParamString = request.getQueryString() != null ? ("?" + request.getQueryString()) : "";
    multiOptionURIParam = "&multiOptionURI=" + Encode.forUriComponent(baseURL + queryParamString);

    boolean isLocal = false;
    boolean isFederated = false;
    boolean isBasic = false;
    // Enable basic account creation flow if there are no authenticators configured.
    if (configuredAuthenticators == null) {
        isBasic = true;
    }
    JSONArray localAuthenticators = new JSONArray();
    JSONArray federatedAuthenticators = new JSONArray();
    if (configuredAuthenticators != null) {
        for ( int index = 0; index < configuredAuthenticators.length(); index++) {
            JSONObject step = (JSONObject)configuredAuthenticators.get(index);
            int stepId = (int)step.get("stepId");
            if (stepId == 1 || stepId == 2) {
                JSONArray tempLocalAuthenticators = (JSONArray)step.get("localAuthenticators");
                for (int i = 0; i < tempLocalAuthenticators.length(); i++) {
                    JSONObject localAuth = (JSONObject)tempLocalAuthenticators.get(i);
                    localAuthenticators.put(localAuth);
                    // check basic authenticator
                    if (StringUtils.equalsIgnoreCase(BASIC_AUTHENTICATOR, (String)localAuth.get("type"))) {
                        isLocal = true;
                    }
                }
            }
            if (stepId == 1) {
                federatedAuthenticators = (JSONArray)step.get("federatedAuthenticators");
                if (federatedAuthenticators.length() > 0) {
                    isFederated = true;
                }
            }
        }
    }

    if (request.getParameter(Constants.MISSING_CLAIMS) != null) {
        missingClaimList = request.getParameter(Constants.MISSING_CLAIMS).split(",");
    }
    if (request.getParameter("missingClaimsDisplayName") != null) {
        missingClaimDisplayName = request.getParameter("missingClaimsDisplayName").split(",");
    }

    if (errorCodeObj != null) {
        errorCode = errorCodeObj.toString();
    }
    if (SelfRegistrationStatusCodes.ERROR_CODE_INVALID_TENANT.equalsIgnoreCase(errorCode)) {
        errorMsg = "Invalid tenant domain - " + user.getTenantDomain();
    } else if (SelfRegistrationStatusCodes.ERROR_CODE_USER_ALREADY_EXISTS.equalsIgnoreCase(errorCode)) {
        errorMsg = "Username '" + username + "' is already taken. Please pick a different username";
        isFederated = false;
    } else if (SelfRegistrationStatusCodes.ERROR_CODE_SELF_REGISTRATION_DISABLED.equalsIgnoreCase(errorCode)) {
        errorMsg = "Self registration is disabled for tenant - " + user.getTenantDomain();
    } else if (SelfRegistrationStatusCodes.CODE_USER_NAME_INVALID.equalsIgnoreCase(errorCode)) {
        if (request.getAttribute("errorMessage") != null) {
            errorMsg = (String) request.getAttribute("errorMessage");
        } else {
            errorMsg = user.getUsername() + " is an invalid user name. Please pick a valid username.";
        }
    } else if (StringUtils.equalsIgnoreCase(SelfRegistrationStatusCodes.ERROR_CODE_INVALID_EMAIL_USERNAME,
            errorCode)) {
        errorMsg = "Username is invalid. Username should be in email format.";
    } else if (errorMsgObj != null) {
        errorMsg = errorMsgObj.toString();
    }

    /**
    * For SaaS applications, read the user tenant from parameters.
    */
    String srtenantDomain = request.getParameter("srtenantDomain");
    if (isSaaSApp && StringUtils.isNotBlank(srtenantDomain)) {
        tenantDomain = srtenantDomain;
    }

    if (skipSignUpEnableCheck) {
        consentPurposeGroupName = "JIT";
    }

    if (StringUtils.isBlank(callback) || StringUtils.equalsIgnoreCase(callback, "null")) {
        callback = Encode.forHtmlAttribute(IdentityManagementEndpointUtil.getUserPortalUrl(
                application.getInitParameter(IdentityManagementEndpointConstants.ConfigConstants.USER_PORTAL_URL), tenantDomain));
    }

    /**
    * If backToUrl is null get to access url of the application.
    */
    if (StringUtils.equalsIgnoreCase(backToUrl,"null")) {
        try {
                // Retrieve application access url to redirect user back to the application.
                backToUrl = applicationDataRetrievalClient.getApplicationAccessURL(tenantDomain, sp);
            } catch (Exception e) {
                backToUrl = null;
        }
    }

    String purposes = selfRegistrationMgtClient.getPurposes(tenantDomain, consentPurposeGroupName,
            consentPurposeGroupType);
    boolean hasPurposes = StringUtils.isNotEmpty(purposes);
    Claim[] claims = new Claim[0];

    /**
     * Change consentDisplayType to "template" inorder to use a custom html template.
     * other Default values are "row" and "tree".
     */
    String consentDisplayType = "row";

    if (hasPurposes) {
        defaultPurposeCatId = selfRegistrationMgtClient.getDefaultPurposeId(tenantDomain);
        uniquePIIs = IdentityManagementEndpointUtil.getUniquePIIs(purposes);
        if (MapUtils.isNotEmpty(uniquePIIs)) {
            piisConfigured = true;
        }
    }

    List<Claim> claimsList;
    UsernameRecoveryApi usernameRecoveryApi = new UsernameRecoveryApi();
    try {
        claimsList = usernameRecoveryApi.claimsGet(tenantDomain, false);
        uniquePIIs = IdentityManagementEndpointUtil.fillPiisWithClaimInfo(uniquePIIs, claimsList);
        if (uniquePIIs != null) {
            claims = uniquePIIs.values().toArray(new Claim[0]);
        }
        IdentityManagementEndpointUtil.addReCaptchaHeaders(request, usernameRecoveryApi.getApiClient().getResponseHeaders());

    } catch (ApiException e) {
        IdentityManagementEndpointUtil.addErrorInformation(request, e);
        if (!StringUtils.isBlank(username)) {
            request.setAttribute("username", username);
        }
        request.getRequestDispatcher("error.jsp").forward(request, response);
        return;
    }

    /**
    * Temporarily read recapcha status from password recovery endpoint.
    */
    ReCaptchaApi reCaptchaApi = new ReCaptchaApi();
    try {
        ReCaptchaProperties reCaptchaProperties = reCaptchaApi.getReCaptcha(tenantDomain, true, "ReCaptcha",
                "password-recovery");

        if (reCaptchaProperties.getReCaptchaEnabled()) {
            Map<String, List<String>> headers = new HashMap<>();
            headers.put("reCaptcha", Arrays.asList(String.valueOf(true)));
            headers.put("reCaptchaAPI", Arrays.asList(reCaptchaProperties.getReCaptchaAPI()));
            headers.put("reCaptchaKey", Arrays.asList(reCaptchaProperties.getReCaptchaKey()));
            IdentityManagementEndpointUtil.addReCaptchaHeaders(request, headers);
        }
    } catch (ApiException e) {
        request.setAttribute("error", true);
        request.setAttribute("errorMsg", e.getMessage());
        if (!StringUtils.isBlank(username)) {
            request.setAttribute("username", username);
        }
        request.getRequestDispatcher("error.jsp").forward(request, response);
        return;
    }

    boolean reCaptchaEnabled = false;
    if (request.getAttribute("reCaptcha") != null && "TRUE".equalsIgnoreCase((String) request.getAttribute("reCaptcha"))) {
        reCaptchaEnabled = true;
    }
%>
<%!
    /**
     * Retrieve all county codes and country display names and
     * store into a map where key/value pair is defined as the
     * country code/country display name.
     *
     * @return {Map<string, string>}
     */
    private Map<String, String> getCountryList() {
        String[] countryCodes = Locale.getISOCountries();

        Map<String, String> mapCountries = new TreeMap<>();

        for (String countryCode : countryCodes) {
            Locale locale = new Locale("", countryCode);
            String country_code = locale.getCountry();
            String country_display_name = locale.getDisplayCountry();
            mapCountries.put(country_code, country_display_name);
        }

        return mapCountries;
    }
%>

<!doctype html>
<html lang="en-US">
<head>
    <%-- header --%>
    <%
        File headerFile = new File(getServletContext().getRealPath("extensions/header.jsp"));
        if (headerFile.exists()) {
    %>
        <jsp:include page="extensions/header.jsp"/>
    <% } else { %>
        <jsp:include page="includes/header.jsp"/>
    <% } %>
    <%
        if (reCaptchaEnabled) {
    %>
        <script src="https://www.google.com/recaptcha/api.js" async defer></script>
    <%
        }
    %>
    <link rel="stylesheet" href="libs/addons/calendar.min.css"/>
</head>
<body class="login-portal layout recovery-layout">
    <layout:main layoutName="<%= layout %>" layoutFileRelativePath="<%= layoutFileRelativePath %>" data="<%= layoutData %>" >
        <layout:component componentName="ProductHeader" >
            <%-- product-title --%>
            <%
                File productTitleFile = new File(getServletContext().getRealPath("extensions/product-title.jsp"));
                if (productTitleFile.exists()) {
            %>
                <jsp:include page="extensions/product-title.jsp"/>
            <% } else { %>
                <jsp:include page="includes/product-title.jsp"/>
            <% } %>
        </layout:component>
        <layout:component componentName="MainSection" >
            <div class="ui segment">
                <h3 class="ui header" data-testid="self-registration-username-request-page-header">
                    <%=IdentityManagementEndpointUtil.i18n(recoveryResourceBundle, "Start.signing.up")%>
                </h3>

                <% if (error) { %>
                <div class="ui negative message" id="server-error-msg">
                    <%= IdentityManagementEndpointUtil.i18nBase64(recoveryResourceBundle, errorMsg) %>
                </div>
                <% } %>

                <!-- show continue with email button -->
                <div id="continue-with-email" hidden="hidden">
                    <div class="buttons mt-4">
                        <button
                            id="ContinueWithEmail"
                            class="ui primary button large fluid"
                            type="submit"
                            data-testid="continue-with-email-button"
                            onclick="showEmail()"
                        >
                            Continue with email
                        </button>
                    </div>
                    <div class="ui horizontal divider">
                    Or
                    </div>
                </div>

                <!-- federated authenticators -->
                <div class="ui divider hidden"></div>
                <div id="federated-authenticators" hidden="hidden">
                    <%
                    for (int i = 0; i < federatedAuthenticators.length(); i++) {

                        JSONObject federatedAuthenticator = (JSONObject) federatedAuthenticators.get(i);
                        String name = (String)federatedAuthenticator.get("name");
                        String type = (String)federatedAuthenticator.get("type");
                        String displayName = name;

                        String imageURL = "libs/themes/asgardio/assets/images/identity-providers/enterprise-idp-illustration.svg";
                        try {
                            IdentityProviderDataRetrievalClient identityProviderDataRetrievalClient = new IdentityProviderDataRetrievalClient();
                            imageURL = identityProviderDataRetrievalClient.getIdPImage(tenantDomain, name);
                        } catch (IdentityProviderDataRetrievalClientException e) {
                            // Exception is ignored and the default `imageURL` value will be used as a fallback.
                        }
                        // If any IdP's name starts with `Sign in with`, then we need to remove the `Sign in with` part.
                        // If not, the UI will look weird with labels like `Sign in with Sign In With Google`.
                        String EXTERNAL_CONNECTION_PREFIX = "sign in with";
                        if (StringUtils.startsWithIgnoreCase(name, EXTERNAL_CONNECTION_PREFIX)) {
                            displayName = name.substring(EXTERNAL_CONNECTION_PREFIX.length());
                        }

                        if (StringUtils.equals(type,GOOGLE_AUTHENTICATOR)) {
                    %>

                    <div class="social-login blurring social-dimmer">
                        <div class="field">
                            <button type="button"
                                class="ui button"
                                data-testid="sign-up-with-google"
                                onclick="handleNoDomain(this,
                                                    '<%=Encode.forJavaScriptAttribute(Encode.forUriComponent(name))%>',
                                                    '<%=Encode.forJavaScriptAttribute(Encode.forUriComponent(type))%>')"
                            >
                            <img class="ui image" src="libs/themes/asgardio/assets/images/identity-providers/google-idp-illustration.svg">
                            <span>Continue with <%=Encode.forHtmlContent(displayName)%></span>
                            </button>
                        </div>
                    </div>
                    <br>
                    <%
                        } else if (StringUtils.equals(type,GITHUB_AUTHENTICATOR)) {
                    %>
                    <div class="social-login blurring social-dimmer">
                        <div class="field">
                            <button type="button"
                                class="ui button"
                                data-testid="sign-up-with-github"
                                onclick="handleNoDomain(this,
                                                    '<%=Encode.forJavaScriptAttribute(Encode.forUriComponent(name))%>',
                                                    '<%=Encode.forJavaScriptAttribute(Encode.forUriComponent(type))%>')"
                            >
                            <img class="ui image" src="libs/themes/asgardio/assets/images/identity-providers/github-idp-illustration.svg">
                            <span>Continue with <%=Encode.forHtmlContent(displayName)%></span>
                            </button>
                        </div>
                    </div>
                    <br>
                    <%
                        } else if (StringUtils.equals(type,FACEBOOK_AUTHENTICATOR)) {
                    %>
                    <div class="social-login blurring social-dimmer">
                        <div class="field">
                            <button type="button"
                                class="ui button"
                                data-testid="sign-up-with-facebook"
                                onclick="handleNoDomain(this,
                                                    '<%=Encode.forJavaScriptAttribute(Encode.forUriComponent(name))%>',
                                                    '<%=Encode.forJavaScriptAttribute(Encode.forUriComponent(type))%>')"
                            >
                            <img class="ui image" src="libs/themes/asgardio/assets/images/identity-providers/facebook-idp-illustration.svg">
                            <span>Continue with <%=Encode.forHtmlContent(displayName)%></span>
                            </button>
                        </div>
                    </div>
                    <br>
                    <%
                        } else {
                    %>
                    <div class="social-login blurring social-dimmer">
                        <div class="field">
                            <button
                                type="button"
                                class="ui button"
                                data-testid='sign-up-with-<%=Encode.forHtmlContent(name)%>'
                                onclick="handleNoDomain(this,
                                    '<%=Encode.forJavaScriptAttribute(Encode.forUriComponent(name))%>',
                                    '<%=Encode.forJavaScriptAttribute(Encode.forUriComponent(type))%>')"
                                >
                                    <img class="ui image" src="<%=Encode.forHtmlAttribute(imageURL)%>">
                                    <span>Continue with <%=Encode.forHtmlContent(displayName)%></span>
                            </button>
                        </div>
                    </div>
                    <br>
                    <%
                        }
                    }
                    %>
                    <div style="text-align: left;">
                        <%--Terms/Privacy Policy--%>
                        <p class="mt-2 mb-0 left privacy">When you continue, you are agreeing to our
                            <a href="<%= StringEscapeUtils.escapeHtml4(termsOfUseURL) %>" target="_blank"
                            data-testid="registration-form-tos-link"
                            rel="noopener noreferrer">
                                terms of service</a> and
                            <a href="<%= StringEscapeUtils.escapeHtml4(privacyPolicyURL) %>" target="_blank"
                            data-testid="registration-form-tos-link"
                            rel="noopener noreferrer">
                                privacy policy</a>
                        </p>
                        <%--End Terms/Privacy Policy--%>
                        <div class="ui divider hidden"></div>
                        <%
                            if (!StringUtils.equalsIgnoreCase(backToUrl,"null") && !StringUtils.isBlank(backToUrl)) {
                        %>
                        <div class="buttons mt-2">
                            <div class="field external-link-container text-small">
                                <%=IdentityManagementEndpointUtil.i18n(recoveryResourceBundle,
                                        "Already.have.an.account")%>
                                <a href="<%=backToUrl%>">
                                    <%=IdentityManagementEndpointUtil.i18n(recoveryResourceBundle, "Sign.in")%>
                                </a>
                            </div>
                        </div>
                        <%
                            }
                        %>
                    </div>
                </div>

                <!-- validation -->
                <div class="ui negative message" id="error-msg" hidden="hidden"></div>
                <div class="segment-form" id="basic-form" hidden="hidden">
                    <form class="ui large form" action="processregistration.do" method="post" id="register" novalidate>
                        <div id="usernameField" class="field required" >
                            <input id="isSaaSApp" name="isSaaSApp" type="hidden"value="<%=isSaaSApp%>">
                        <% if (isPasswordProvisionEnabled || !skipSignUpEnableCheck) { %>
                            <div class="ui divider hidden"></div>
                            <label><%=IdentityManagementEndpointUtil.i18n(recoveryResourceBundle, "Email")%></label>
                            <div class="ui fluid left icon input">
                                <input
                                    type="email"
                                    id="usernameUserInput"
                                    value=""
                                    name="http://wso2.org/claims/emailaddress"
                                    tabindex="1"
                                    placeholder="Enter your email"
                                    data-testid="self-register-page-username-input"
                                    autocomplete="off"
                                    required
                                />
                                <i aria-hidden="true" class="envelope outline icon"></i>
                                <input id="username" name="username" type="hidden"
                                    <% if(skipSignUpEnableCheck) {%> value="<%=Encode.forHtmlAttribute(username)%>" <%}%>>
                            </div>
                            <div class="mt-1" id="username-error-msg" hidden="hidden">
                                <div class="ui grid">
                                    <div class="one wide column">
                                        <i class="red exclamation circle icon"></i>
                                    </div>
                                    <div class="fourteen wide column validation-error-message" id="username-error-msg-text"></div>
                                </div>
                            </div>
                        </div>
                        <div id="passwordField" class="field required">
                            <label><%=IdentityManagementEndpointUtil.i18n(recoveryResourceBundle, "Password")%></label>
                            <div class="ui fluid left icon input addon-wrapper">
                                <input
                                    type="password"
                                    id="passwordUserInput"
                                    value=""
                                    name="passwordUserInput"
                                    tabindex="1"
                                    placeholder="Enter your password"
                                    data-testid="self-register-page-password-input"
                                    autocomplete="new-password"
                                    required
                                />
                                <i aria-hidden="true" class="lock icon"></i>
                                <i id="password-eye" class="eye icon right-align password-toggle slash" onclick="showPassword()"></i>
                                <input id="password" name="password" type="hidden"
                                    <% if(skipSignUpEnableCheck) {%> value="<%=Encode.forHtmlAttribute(username)%>" <%}%>>
                            </div>
                            <div class="mt-1" id="password-error-msg" hidden="hidden">
                                <div class="ui grid">
                                    <div class="one wide column">
                                        <i class="red exclamation circle icon"></i>
                                    </div>
                                    <div class="fourteen wide column validation-error-message" id="password-error-msg-text"></div>
                                </div>
                            </div>
                        </div>
                        <input name="previous_step" type="hidden" id="previous_step" />

                        <% Map<String, String[]> requestMap = request.getParameterMap();
                            for (Map.Entry<String, String[]> entry : requestMap.entrySet()) {
                                String key = Encode.forHtmlAttribute(entry.getKey());
                                String value = Encode.forHtmlAttribute(entry.getValue()[0]); %>
                        <div class="field">
                            <input id="<%= key%>" name="<%= key%>" type="hidden"
                                value="<%=value%>" class="form-control">
                        </div>
                        <% } %>
                        <%-- Add claims sections --%>
                            <div>
                                <%
                                    Claim firstNamePII =
                                        uniquePIIs.get(IdentityManagementEndpointConstants.ClaimURIs.FIRST_NAME_CLAIM);
                                    Claim lastNamePII =
                                        uniquePIIs.get(IdentityManagementEndpointConstants.ClaimURIs.LAST_NAME_CLAIM);
                                    if (firstNamePII != null) {
                                        String firstNameValue = request.getParameter(IdentityManagementEndpointConstants.ClaimURIs.FIRST_NAME_CLAIM);
                                %>
                                    <div <% if (lastNamePII != null) { %> class="two fields mb-0" <%} %> >
                                        <div id="firstNameField"
                                        <% if (firstNamePII.getRequired()) { %> class="field form-group required" <%}
                                                else {%> class="field"<%}%>>
                                            <label class="control-label"><%=IdentityManagementEndpointUtil.i18n(recoveryResourceBundle, "First.name")%>
                                            </label>
                                            <input id="firstNameUserInput" type="text" name="http://wso2.org/claims/givenname" class="form-control"
                                                <% if (firstNamePII.getRequired()) {%> required <%}%>
                                                <% if (skipSignUpEnableCheck && StringUtils.isNotEmpty(firstNameValue)) { %>
                                                value="<%= Encode.forHtmlAttribute(firstNameValue)%>" disabled <% } %>
                                                placeholder="<%=IdentityManagementEndpointUtil.i18n(recoveryResourceBundle, "First.name")%>"/>
                                                <div class="mt-1" id="firstname-error-msg" hidden="hidden">
                                                    <div class="ui grid">
                                                        <div class="one wide column">
                                                            <i class="red exclamation circle icon"></i>
                                                        </div>
                                                        <div class="ten wide column validation-error-message" id="firstname-error-msg-text"></div>
                                                    </div>
                                                </div>
                                        </div>
                                        <%}%>

                                        <%
                                            if (lastNamePII != null) {
                                                String lastNameValue =
                                                        request.getParameter(IdentityManagementEndpointConstants.ClaimURIs.LAST_NAME_CLAIM);
                                        %>

                                        <div id="lastNameField"
                                            <% if (lastNamePII.getRequired()) { %> class="field form-group required" <% }
                                                else { %> class="field form-group"<% } %>>
                                            <label class="control-label"><%=IdentityManagementEndpointUtil.i18n(recoveryResourceBundle, "Last.name")%>
                                            </label>
                                            <input id="lastNameUserInput" type="text" name="http://wso2.org/claims/lastname" class="form-control"
                                                <% if (lastNamePII.getRequired()) {%> required <%}%>
                                                <% if (skipSignUpEnableCheck && StringUtils.isNotEmpty(lastNameValue)) { %>
                                                value="<%= Encode.forHtmlAttribute(lastNameValue)%>" disabled <% } %>
                                                placeholder="<%=IdentityManagementEndpointUtil.i18n(recoveryResourceBundle, "Last.name")%>"
                                            />
                                            <div class="mt-1" id="lastname-error-msg" hidden="hidden">
                                                <div class="ui grid">
                                                    <div class="one wide column">
                                                        <i class="red exclamation circle icon"></i>
                                                    </div>
                                                    <div class="ten wide column validation-error-message" id="lastname-error-msg-text"></div>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="mb-3"></div>

                                <%}%>
                                <%
                                    if (callback != null) {
                                %>
                                <% for (int index = 0; index < missingClaimList.length; index++) {
                                    String claim = missingClaimList[index];
                                    String claimDisplayName = missingClaimDisplayName[index];
                                    if (!StringUtils
                                            .equals(claim, IdentityManagementEndpointConstants.ClaimURIs.FIRST_NAME_CLAIM)
                                            && !StringUtils
                                            .equals(claim, IdentityManagementEndpointConstants.ClaimURIs.LAST_NAME_CLAIM)
                                            && !StringUtils
                                            .equals(claim, IdentityManagementEndpointConstants.ClaimURIs.EMAIL_CLAIM)) {
                                %>
                                <div class="required field">
                                    <input type="text" name="missing-<%=Encode.forHtmlAttribute(claim)%>"
                                        id="<%=Encode.forHtmlAttribute(claim)%>" class="form-control"
                                        onblur="showFieldValidationStatus(this)"
                                        oninput="hideFieldValidationStatus(this)"
                                        required="required" placeholder=<%=IdentityManagementEndpointUtil.i18nBase64(recoveryResourceBundle, claimDisplayName)%>>
                                </div>
                                <% }
                                }%>
                                <%
                                    }
                                    List<String> missingClaims = null;
                                    if (ArrayUtils.isNotEmpty(missingClaimList)) {
                                        missingClaims = Arrays.asList(missingClaimList);
                                    }
                                    for (Claim claim : claims) {
                                        if ((CollectionUtils.isEmpty(missingClaims) || !missingClaims.contains(claim.getUri())) &&
                                                !StringUtils.equals(claim.getUri(), IdentityManagementEndpointConstants.ClaimURIs.FIRST_NAME_CLAIM) &&
                                                !StringUtils.equals(claim.getUri(), IdentityManagementEndpointConstants.ClaimURIs.LAST_NAME_CLAIM) &&
                                                !StringUtils.equals(claim.getUri(), IdentityManagementEndpointConstants.ClaimURIs.EMAIL_CLAIM) &&
                                                !StringUtils.equals(claim.getUri(), IdentityManagementEndpointConstants.ClaimURIs.CHALLENGE_QUESTION_URI_CLAIM) &&
                                                !StringUtils.equals(claim.getUri(), IdentityManagementEndpointConstants.ClaimURIs.CHALLENGE_QUESTION_1_CLAIM) &&
                                                !StringUtils.equals(claim.getUri(), IdentityManagementEndpointConstants.ClaimURIs.CHALLENGE_QUESTION_2_CLAIM) &&
                                                !StringUtils.equals(claim.getUri(), "http://wso2.org/claims/groups") &&
                                                !StringUtils.equals(claim.getUri(), "http://wso2.org/claims/role") &&
                                                !StringUtils.equals(claim.getUri(), "http://wso2.org/claims/url") &&
                                                !(claim.getReadOnly() != null ? claim.getReadOnly() : false)) {
                                            String claimURI = claim.getUri();
                                            String claimValue = request.getParameter(claimURI);
                                            String[] claimFields = claimURI.split("/");
                                            String claimName = claimFields[claimFields.length-1];
                                            String claimFieldID = claimName + "_field";
                                            String claimErrorMsg = claimName + "_error";
                                            String claimErrorMsgText = claimName + "_error_text";
                                %>
                                    <div  id= "<%=IdentityManagementEndpointUtil.i18nBase64(recoveryResourceBundle, claimFieldID)%>"
                                    <% if (claim.getRequired()) { %> class="field form-group required" <%}
                                                else {%> class="field"<%}%>  >
                                        <label class="control-label">
                                            <%=IdentityManagementEndpointUtil.i18nBase64(recoveryResourceBundle, claim.getDisplayName())%>
                                        </label>
                                    <% if(StringUtils.equals(claim.getUri(), "http://wso2.org/claims/country")) {%>
                                        <div class="ui fluid search selection dropdown"  id="country-dropdown"
                                            data-testid="country-dropdown">
                                            <input type="hidden"
                                                id="country"
                                                name="<%= Encode.forHtmlAttribute(claimURI) %>"
                                                <% if (claim.getRequired()) { %>
                                                    required
                                                <% }%>
                                                <% if(skipSignUpEnableCheck && StringUtils.isNotEmpty(claimValue)) {%>
                                                    value="<%= Encode.forHtmlAttribute(claimValue)%>" disabled<%}%>
                                            />
                                            <i class="dropdown icon"></i>
                                            <div class="default text">Enter Country</div>
                                            <div class="menu">
                                                <c:forEach items="<%=getCountryList()%>" var="country">
                                                    <div class="item" data-value="${country.value}">
                                                        <i class="${country.key.toLowerCase()} flag"></i>
                                                            ${country.value}
                                                    </div>
                                                </c:forEach>
                                            </div>
                                        </div>
                                    <% } else if (StringUtils.equals(claim.getUri(), "http://wso2.org/claims/dob")) { %>
                                        <div class="ui calendar" id="date_picker">
                                            <div class="ui input right icon" style="width: 100%;">
                                                <i class="calendar icon"></i>
                                                <input type="text"
                                                        autocomplete="off"
                                                        name="<%= Encode.forHtmlAttribute(claimURI) %>"
                                                        id="birthOfDate"
                                                        <% if (claim.getRequired()) { %>
                                                            required
                                                        <% } %>
                                                        placeholder="Enter Birth Date"
                                                    <% if(skipSignUpEnableCheck && StringUtils.isNotEmpty(claimValue)) {%>
                                                        value="<%= Encode.forHtmlAttribute(claimValue)%>" disabled<%}%>
                                                />
                                            </div>
                                        </div>
                                    <% } else { %>
                                            <input type="text" name="<%= Encode.forHtmlAttribute(claimURI) %>"
                                                class="form-control"
                                                onblur="showFieldValidationStatus(this)"
                                                oninput="hideFieldValidationStatus(this)"
                                                <% if (claim.getValidationRegex() != null) { %>
                                                pattern="<%= Encode.forHtmlContent(claim.getValidationRegex()) %>"
                                                <% } %>
                                                <% if (claim.getRequired()) { %>
                                                    required
                                                <% } %>
                                                <% if (StringUtils.equals(claim.getUri(), "http://wso2.org/claims/mobile")) { %>
                                                    id="mobileNumber"
                                            <% }%>
                                                placeholder="Enter <%=IdentityManagementEndpointUtil.i18nBase64(recoveryResourceBundle, claim.getDisplayName())%>"
                                                <% if(skipSignUpEnableCheck && StringUtils.isNotEmpty(claimValue)) {%>
                                                value="<%= Encode.forHtmlAttribute(claimValue)%>" disabled<%}%>
                                            />
                                    <% } %>
                                    <div class="mt-1" id="<%=IdentityManagementEndpointUtil.i18nBase64(recoveryResourceBundle, claimErrorMsg)%>" hidden="hidden">
                                        <div class="ui grid">
                                            <div class="one wide column">
                                                <i class="red exclamation circle icon"></i>
                                            </div>
                                            <div class="fourteen wide column validation-error-message"
                                            id="<%=IdentityManagementEndpointUtil.i18nBase64(recoveryResourceBundle, claimErrorMsgText)%>"></div>
                                        </div>
                                    </div>
                                    </div>
                                <%
                                    }
                                }
                                %>

                            </div>
                            <% } else { %>
                            <div>
                                <div class="field">
                                    <label class="control-label">User Name
                                    </label>
                                    <input type="text" class="form-control"
                                        value="<%=Encode.forHtmlAttribute(username)%>" disabled>
                                </div>
                                <%
                                    for (Claim claim : claims) {
                                        String claimUri = claim.getUri();
                                        String claimValue = request.getParameter(claimUri);

                                        if (StringUtils.isNotEmpty(claimValue)) { %>
                                <div class="field">
                                    <label class="control-label">
                                        <%=IdentityManagementEndpointUtil.i18nBase64(recoveryResourceBundle, claim.getDisplayName())%>
                                    </label>
                                    <input type="text" class="form-control"
                                        value="<%= Encode.forHtmlAttribute(claimValue)%>" disabled>
                                </div>
                                <% }
                                }%>
                            </div>
                            <% } %>
                            <% if (skipSignUpEnableCheck) { %>
                            <div class="field">
                                <input type="hidden" name="sessionDataKey" value='<%=Encode.forHtmlAttribute
                                        (request.getParameter("sessionDataKey"))%>'/>
                            </div>
                            <div class="field">
                                <input type="hidden" name="policy" value='<%=Encode.forHtmlAttribute
                                        (IdentityManagementServiceUtil.getInstance().getServiceContextURL().replace("/services",
                                        "/authenticationendpoint/privacy_policy.do"))%>'/>
                            </div>
                            <% }

                                if (hasPurposes) {
                            %>
                            <div class="ui divider hidden"></div>
                            <div class="ui secondary left aligned segment">
                                <p>
                                    <%=IdentityManagementEndpointUtil.i18n(recoveryResourceBundle,
                                        "Need.consent.for.following.purposes")%>
                                    <span>
                                        <%=IdentityManagementEndpointUtil.i18n(recoveryResourceBundle,
                                            "I.consent.to.use.them")%>
                                    </span>
                                    <%
                                        if (consentDisplayType == "template") {
                                    %>
                                    <%--User Consents from Template--%>
                                        <div class="consent-statement"></div>
                                    <%--End User Consents from Template--%>
                                    <% } else if (consentDisplayType == "tree") { %>
                                    <%--User Consents Tree--%>
                                        <div id="tree-table"></div>
                                    <%--End User Consents Tree--%>
                                    <%
                                    } else if (consentDisplayType == "row") {
                                    %>
                                    <%--User Consents Row--%>
                                        <div id="row-container"></div>
                                    <%--End User Consents Row--%>
                                    <%
                                        }
                                    %>
                                </p>
                            </div>
                            <%
                                }
                            %>
                            <div class="field">
                                <%
                                    if (reCaptchaEnabled) {
                                        String reCaptchaKey = CaptchaUtil.reCaptchaSiteKey();
                                %>
                                <div class="ui divider hidden"></div>
                                <div class="field">
                                    <div class="g-recaptcha"
                                        data-sitekey="<%=Encode.forHtmlAttribute(reCaptchaKey)%>"
                                        data-theme="light"
                                    >
                                    </div>
                                </div>
                                <%
                                    }
                                %>
                                <div class="ui divider hidden"></div>
                                <%
                                if (!isFederated) {
                                %>
                                <%--Terms/Privacy Policy--%>
                                    <p class="mt-5 mb-0 privacy">When you click Sign Up, you are agreeing to our
                                        <a href="<%= StringEscapeUtils.escapeHtml4(termsOfUseURL) %>" target="_blank"
                                        data-testid="registration-form-tos-link"
                                        rel="noopener noreferrer">
                                            terms of service</a> and
                                        <a href="<%= StringEscapeUtils.escapeHtml4(privacyPolicyURL) %>" target="_blank"
                                        data-testid="registration-form-tos-link"
                                        rel="noopener noreferrer">
                                            privacy policy</a>
                                    </p>
                                    <%--End Terms/Privacy Policy--%>
                                <%
                                }
                                %>
                                <div class="field">
                                    <input id="isSelfRegistrationWithVerification" type="hidden"
                                        name="isSelfRegistrationWithVerification"
                                        value="true"/>
                                    <%
                                        if (!IdentityTenantUtil.isTenantQualifiedUrlsEnabled()) {
                                    %>
                                    <input id="tenantDomain" name="tenantDomain" type="hidden"
                                        value="<%= Encode.forHtmlAttribute(tenantDomain) %>"/>
                                    <%
                                        }
                                    %>
                                    <%
                                        if (isSaaSApp) {
                                    %>
                                    <input id="srtenantDomain" name="srtenantDomain" type="hidden"
                                        value="<%=Encode.forHtmlAttribute(tenantDomain)%>"/>
                                    <%
                                        }
                                    %>
                                    <%
                                        if (StringUtils.isNotBlank(sp)) {
                                    %>
                                    <input id="sp" name="sp" type="hidden" value="<%=sp%>"/>
                                    <%
                                        }
                                    %>
                                </div>

                            </div>
                        <div class="buttons mt-4">
                            <button id="registrationSubmit" class="ui primary button large fluid" type="submit">
                                <%=IdentityManagementEndpointUtil.i18n(recoveryResourceBundle,
                                        "Register")%>
                            </button>
                        </div>
                        <div class="ui divider hidden"></div>
                        <%
                            if (!StringUtils.equalsIgnoreCase(backToUrl,"null") && !StringUtils.isBlank(backToUrl)) {
                        %>
                        <div class="buttons mt-2">
                            <div class="field external-link-container text-small">
                                <%=IdentityManagementEndpointUtil.i18n(recoveryResourceBundle,
                                        "Already.have.an.account")%>
                                <a href="<%=backToUrl%>">
                                    <%=IdentityManagementEndpointUtil.i18n(recoveryResourceBundle, "Sign.in")%>
                                </a>
                            </div>
                        </div>
                        <%
                            }
                        %>
                    </form>
                </div>
            </div>
        </layout:component>
        <layout:component componentName="ProductFooter" >
            <%-- product-footer --%>
            <%
                File productFooterFile = new File(getServletContext().getRealPath("extensions/product-footer.jsp"));
                if (productFooterFile.exists()) {
            %>
                <jsp:include page="extensions/product-footer.jsp"/>
            <% } else { %>
                <jsp:include page="includes/product-footer.jsp"/>
            <% } %>
        </layout:component>
    </layout:main>

    <%-- footer --%>
    <%
        File footerFile = new File(getServletContext().getRealPath("extensions/footer.jsp"));
        if (footerFile.exists()) {
    %>
        <jsp:include page="extensions/footer.jsp"/>
    <% } else { %>
        <jsp:include page="includes/footer.jsp"/>
    <% } %>

    <script>
        var registrationDataKey = "registrationData";
        var $registerForm = $("#register");
        var validUsername = false;
        var validPassword = false;

        // Reloads the page if the page is loaded by going back in history.
        // Fixes issues with Firefox.
        window.addEventListener( "pageshow", function ( event ) {
            var historyTraversal = event.persisted ||
                                ( typeof window.performance != "undefined" &&
                                    window.performance.navigation.type === 2 );

            if ( historyTraversal ) {
                if($registerForm){
                    $registerForm.data("submitted", false);
                }
            }
        });

        function goBack() {
            window.history.back();
        }

        // Fires when username field lose focus.
        $('#usernameUserInput').bind('blur', function () {
            showUsernameValidationStatus();
        });

        // Fires when password field lose focus.
        $('#passwordUserInput').bind('blur', function () {
            showPasswordValidationStatus();
        });

        // Fires when firstname field lose focus.
        $('#firstNameUserInput').bind('blur', function () {
            showFirstNameValidationStatus();
        });

        // Fires when lastname field lose focus.
        $('#lastNameUserInput').bind('blur', function () {
            showLastNameValidationStatus();
        });

        // Fires when mobile field lose focus.
        $('#mobileNumber').bind('blur', function () {
            showMobileNumberValidationStatus();
        });

        // Fires when country field lose focus.
        $('#country').bind('blur', function () {
            showCountryValidationStatus();
        });

        // Fires on username field input.
        $('#usernameUserInput').bind('input', function () {
            hideUsernameValidationStatus();
        });

        // Fires on password field input.
        $('#passwordUserInput').bind('input', function () {
            hidePasswordValidationStatus();
        });

        // Fires on firstname field input.
        $('#firstNameUserInput').bind('input', function () {
            hideFirstNameValidationStatus();
        });

        // Fires on lastname field input.
        $('#lastNameUserInput').bind('input', function () {
            hideLastNameValidationStatus();
        });

        // Fires on mobile field input.
        $('#mobileNumber').bind('input', function () {
            hideMobileNumberValidationStatus();
        });

        // Fires on country field input.
        $('#country').bind('input', function () {
            hideCountryValidationStatus();
        });

        // Handle form submission preventing double submission.
        $(document).ready(function(){
            <%
                if (error){
            %>
                var registrationData = sessionStorage.getItem(registrationDataKey);
                sessionStorage.removeItem(registrationDataKey);

                if (registrationData){
                    var fields = JSON.parse(registrationData);

                    if (fields.length > 0) {
                        fields.forEach(function(field) {
                            document.getElementsByName(field.name)[0].value = field.value;
                        })
                    }
                }
            <%
                }
            %>

            // Dynamically render the configured authenticators.
            var hasLocal = false;
            var hasFederated = false;
            var isBasicForm = true;
            try {
                var hasLocal=JSON.parse(<%=isLocal%>);
                var hasFederated = JSON.parse(<%=isFederated%>);
                var isBasicForm = JSON.parse(<%=isBasic%>);
            } catch(error) {
                // Do nothing.
            }

            if (hasLocal & hasFederated) {
                $("#continue-with-email").show();
                $("#federated-authenticators").show();
            } else if (hasFederated) {
                $("#federated-authenticators").show();
            } else {
                $("#continue-with-email").hide();
                $("#federated-authenticators").hide();
                if (hasLocal || isBasicForm) {
                    $("#basic-form").show();
                } else {
                    $("#basic-form").hide();
                }
            }

            var container;
            var allAttributes = [];
            var canSubmit;

            var agreementChk = $(".agreement-checkbox input");
            var countryDropdown = $("#country-dropdown");

            countryDropdown.dropdown('hide');
            $("> input.search", countryDropdown).attr("role", "presentation");

            $("#date_picker").calendar({
                type: 'date',
                formatter: {
                    date: function (date, settings) {
                        var EMPTY_STRING = "";
                        var DATE_SEPARATOR = "-";
                        var STRING_ZERO = "0";
                        if (!date) return EMPTY_STRING;
                            var day = date.getDate() + EMPTY_STRING;
                        if (day.length < 2) {
                            day = STRING_ZERO + day;
                        }
                        var month = (date.getMonth() + 1) + EMPTY_STRING;
                        if (month.length < 2) {
                            month = STRING_ZERO + month;
                        }
                        var year = date.getFullYear();
                        return year + DATE_SEPARATOR + month + DATE_SEPARATOR + day;
                    }
                }
            });

            $(".form-info").popup();

            $.fn.preventDoubleSubmission = function() {
                $(this).on("submit", function(e){
                    var $form = $(this);
                    if ($form.data("submitted") === true) {
                        // Previously submitted - don't submit again.
                        e.preventDefault();
                        console.warn("Prevented a possible double submit event");
                    } else {
                        e.preventDefault();

                        var validInput = true;
                        var userName = document.getElementById("username");
                        var usernameUserInput = document.getElementById("usernameUserInput");
                        var password = document.getElementById("password");
                        var passwordUserInput = document.getElementById("passwordUserInput");
                        var unsafeCharPattern = /[<>`\"]/;
                        var elements = document.getElementsByTagName("input");
                        var error_msg = $("#error-msg");
                        var server_error_msg = $("#server-error-msg");

                        // Username validation.
                        if (showUsernameValidationStatus()) {
                            if (usernameUserInput) {
                                userName.value = usernameUserInput.value.trim();
                            }
                        } else {
                            validInput = false;
                        }

                        // Password validation.
                        if (showPasswordValidationStatus()) {
                            if (passwordUserInput) {
                                password.value = passwordUserInput.value.trim();
                            }
                        } else {
                            validInput = false;
                        }

                        // Firstname validation.
                        if (!showFirstNameValidationStatus()) {
                            validInput = false;
                        }

                        // Lastname validation.
                        if (!showLastNameValidationStatus()) {
                            validInput = false;
                        }

                        // Date of birth validation.
                        if (!showDateOfBirthValidationStatus()) {
                            validInput = false;
                        }

                        // Mobile number validation.
                        if (!showMobileNumberValidationStatus()) {
                            validInput = false;
                        }

                        // Country validation
                        if (!showCountryValidationStatus()) {
                            validInput = false;
                        }

                        // Validate the custom input fields.
                        // If at least one of the fields return false,
                        // the input will be invalid.
                        for (i = 0; i < elements.length; i++) {
                            if (!showFieldValidationStatus(elements[i])) {
                                validInput = false;
                            }
                        }

                        // Hide the error message from server if exists.
                        if (server_error_msg.text() !== null && server_error_msg.text().trim() !== ""  ) {
                            $("#error-msg").hide();
                            error_msg = $("#server-error-msg");
                        }

                        <%
                        if(reCaptchaEnabled) {
                            %>
                            var resp = $("[name='g-recaptcha-response']")[0].value;
                            if (resp.trim() == '') {
                                error_msg.text("<%=IdentityManagementEndpointUtil.i18n(recoveryResourceBundle,
                                    "Please.select.reCaptcha")%>");
                                error_msg.show();
                                $("html, body").animate({scrollTop: error_msg.offset().top}, 'slow');
                                validInput = false;
                            }
                            <%
                        }
                        %>

                        // If the input is not valid,
                        // This will return false and prevent form submission.
                        if (!validInput) {
                            return false;
                        }

                        // Mark it so that the next submit can be ignored.
                        $form.data("submitted", true);
                        document.getElementById("register").submit();
                    }
                });

                return this;
            };

            $registerForm.preventDoubleSubmission();

            $("#previous_step").val(window.location.href);
        });

        // Handle selected authenticators.
        function handleNoDomain(elem, key, value) {
            var linkClicked = "link-clicked";
            if ($(elem).hasClass(linkClicked)) {
                console.warn("Preventing multi click.")
            } else {
                $(elem).addClass(linkClicked);

                document.location = "<%=commonauthURL%>?idp=" + key + "&authenticator=" + value +
                    "&sessionDataKey=<%=Encode.forUriComponent(request.getParameter("sessionDataKey"))%>" +
                    "<%=multiOptionURIParam%>";
            }
        }

        // show email
        function showEmail() {
            $("#continue-with-email").hide();
            $("#federated-authenticators").hide();
            $("#basic-form").show();
        }

        // show password function
        function showPassword() {
            var passwordField = $('#passwordUserInput');

            if (passwordField.attr("type") === 'text') {
                passwordField.attr("type", "password")
                document.getElementById("password-eye").classList.add("slash");
            } else {
                passwordField.attr("type", "text")
                document.getElementById("password-eye").classList.remove("slash");
            }
        }

        function showFieldValidationStatus(element) {
            var unsafeCharPattern = /[<>`\"]/;
            var element_claim_name = element.name.split("/").pop();

            if (element_claim_name === "lastname") {
                element_claim_name = "givenname";
            }

            var element_field = element_claim_name + "_field";
            var error_msg_txt = element_claim_name + "_error_text";
            var error_msg_element = element_claim_name + "_error";

            if (element.type === 'text' && element.value != null && element.value.trim() !== ""
                && element.value.length > 250)  {
                $("#" + error_msg_txt).text("Maximum length of the fields cannot exceed 250.");
                $("#" + error_msg_element).show();
                $("#" + element_field).addClass("error");
                var error_msg_txt_element = document.getElementById(error_msg_txt);
                if (error_msg_txt_element) {
                    $("html, body").animate({scrollTop: $("#" + error_msg_txt).offset().top}, 'slow');
                }

                return false;
            }
            if (element.type === 'text' && element.value != null
                && element.value.match(unsafeCharPattern) != null) {
                $("#" + error_msg_txt).text("<%=IdentityManagementEndpointUtil.i18n(recoveryResourceBundle,
                    "For.security.following.characters.restricted")%>");
                $("#" + error_msg_element).show();
                $("#" + element_field).addClass("error");
                var error_msg_txt_element = document.getElementById(error_msg_txt);
                if (error_msg_txt_element) {
                    $("html, body").animate({scrollTop: $("#" + error_msg_txt).offset().top}, 'slow');
                }

                return false;
            }
            if (element.type === 'text' && element.required && element.value.trim() === "") {
                $("#" + error_msg_txt).text("<%=IdentityManagementEndpointUtil.i18n(recoveryResourceBundle,
                "For.required.fields.cannot.be.empty")%>");
                $("#" + error_msg_element).show();
                $("#" + element_field).addClass("error");
                var error_msg_txt_element = document.getElementById(error_msg_txt);
                if (error_msg_txt_element) {
                    $("html, body").animate({scrollTop: $("#" + error_msg_txt).offset().top}, 'slow');
                }

                return false;
            }

            return true;
        }

        function hideFieldValidationStatus(element) {
            var element_claim_name = element.name.split("/").pop();

            if (element_claim_name === "lastname") {
                element_claim_name = "givenname";
            }

            var element_field = element_claim_name + "_field";
            var error_msg_txt = element_claim_name + "_error_text";
            var error_msg_element = element_claim_name + "_error";

            // Remove previous errors.
            $("#" + error_msg_element).hide();
            $("#" + element_field).removeClass("error");
        }

        function showUsernameValidationStatus() {
            var userName = document.getElementById("username");
            var usernameUserInput = document.getElementById("usernameUserInput");
            var usernameField = $("#usernameField");
            var username_error_msg = $("#username-error-msg");
            var server_error_msg = $("#server-error-msg");
            var username_error_msg_text = $("#username-error-msg-text");

            if (server_error_msg.text() !== null && server_error_msg.text().trim() !== ""  ) {
                username_error_msg.hide();
                usernameField.removeClass("error");
            }

            if (usernameUserInput.value.trim() === "")  {
                    username_error_msg_text.text("Enter your email");
                    username_error_msg.show();
                    usernameField.addClass("error");
                    $("html, body").animate({scrollTop: username_error_msg_text.offset().top}, 'slow');

                    return false;
            } else {
                var usernamePattern = /^([\u00C0-\u00FFa-zA-Z0-9_\+\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,10})$/;
                if (!usernamePattern.test(usernameUserInput.value.trim())) {
                    username_error_msg_text.text("Enter a valid email address")
                    username_error_msg.show();
                    usernameField.addClass("error");
                    $("html, body").animate({scrollTop: username_error_msg_text.offset().top}, 'slow');

                    return false;
                } else {
                    // When username is accepted.
                    username_error_msg.hide();
                    usernameField.removeClass("error");

                    return true;
                }
            }
        }

        function hideUsernameValidationStatus() {
            var usernameField = $("#usernameField");
            var username_error_msg = $("#username-error-msg");
            var server_error_msg = $("#server-error-msg");

            if (server_error_msg.text() !== null && server_error_msg.text().trim() !== ""  ) {
                username_error_msg.hide();
                usernameField.removeClass("error");
            }

            username_error_msg.hide();
            usernameField.removeClass("error");
        }

        function showPasswordValidationStatus() {
            var password = document.getElementById("password");
            var passwordUserInput = document.getElementById("passwordUserInput");
            var passwordField = $("#passwordField");
            var password_error_msg = $("#password-error-msg");
            var server_error_msg = $("#server-error-msg");
            var password_error_msg_text = $("#password-error-msg-text");

            if (server_error_msg.text() !== null && server_error_msg.text().trim() !== ""  ) {
                password_error_msg.hide();
                passwordField.removeClass("error");
            }

            if (passwordUserInput.value.trim() === "")  {
                    password_error_msg_text.text("Enter your password");
                    password_error_msg.show();
                    passwordField.addClass("error");
                    $("html, body").animate({scrollTop: password_error_msg_text.offset().top}, 'slow');

                    return false;
            } else {
                var passwordPattern = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/;

                if (!passwordPattern.test(passwordUserInput.value.trim())) {
                    password_error_msg_text.text("Your password should contain at least eight characters, " +
                        "including at least one each from uppercase and lowercase letters and numbers.");
                    password_error_msg.show();
                    passwordField.addClass("error");
                    $("html, body").animate({scrollTop: password_error_msg_text.offset().top}, 'slow');

                    return false;
                } else {
                    // When password is accepted.
                    password_error_msg.hide();
                    passwordField.removeClass("error");

                    return true;
                }
            }
        }

        function hidePasswordValidationStatus() {
            var passwordField = $("#passwordField");
            var password_error_msg = $("#password-error-msg");
            var server_error_msg = $("#server-error-msg");

            if (server_error_msg.text() !== null && server_error_msg.text().trim() !== ""  ) {
                password_error_msg.hide();
                passwordField.removeClass("error");
            }

            password_error_msg.hide();
            passwordField.removeClass("error");
        }

        function showFirstNameValidationStatus() {
            var firstNameUserInput = document.getElementById("firstNameUserInput");
            var firstname_error_msg = $("#firstname-error-msg");
            var firstname_error_msg_text = $("#firstname-error-msg-text");
            var firstname_field= $("#firstNameField");

            if (firstNameUserInput != null && firstNameUserInput.value.trim() === "" && firstNameUserInput.required)  {
                firstname_error_msg_text.text("Required");
                firstname_error_msg.show();
                firstname_field.addClass("error");
                $("html, body").animate({scrollTop: firstname_error_msg_text.offset().top}, 'slow');

                return false;
            } else {
                // When firstname is accepted.
                firstname_error_msg.hide();
                firstname_field.removeClass("error");

                return true;
            }
        }

        function hideFirstNameValidationStatus() {
            var firstname_error_msg = $("#firstname-error-msg");
            var firstname_field= $("#firstNameField");

            firstname_error_msg.hide();
            firstname_field.removeClass("error");
        }

        function showLastNameValidationStatus() {
            var lastNameUserInput = document.getElementById("lastNameUserInput");
            var lastname_error_msg = $("#lastname-error-msg");
            var lastname_error_msg_text = $("#lastname-error-msg-text");
            var lastname_field= $("#lastNameField");

            if (lastNameUserInput != null && lastNameUserInput.value.trim() === "" && lastNameUserInput.required)  {
                lastname_error_msg_text.text("Required");
                lastname_error_msg.show();
                lastname_field.addClass("error");
                $("html, body").animate({scrollTop: lastname_error_msg_text.offset().top}, 'slow');

                return false;
            } else {
                // When lastname is accepted.
                lastname_error_msg.hide();
                lastname_field.removeClass("error");

                return true;
            }
        }

        function hideLastNameValidationStatus() {
            var lastname_error_msg = $("#lastname-error-msg");
            var lastname_field= $("#lastNameField");

            lastname_error_msg.hide();
            lastname_field.removeClass("error");
        }

        function showDateOfBirthValidationStatus() {
            var birthOfDate = document.getElementById("birthOfDate");
            var dob_error_msg = $("#dob_error");
            var dob_error_text = $("#dob_error_text");
            var dob_field = $("#dob_field");

            dob_field.removeClass("error");
            dob_error_msg.hide();

            if (birthOfDate != null && birthOfDate.value != null && birthOfDate.value.trim() !== ""){
                var dobPattern = /^\d{4}-\d{2}-\d{2}$/;
                if (!dobPattern.test(birthOfDate.value)) {
                    dob_error_text.text("Date of Birth is not in the correct format of YYYY-MM-DD")
                    dob_error_msg.show();
                    dob_field.addClass("error");
                    $("html, body").animate({scrollTop: dob_error_text.offset().top}, 'slow');

                    return false;
                }
            } else if (birthOfDate != null && birthOfDate.required && birthOfDate.value.trim() == "") {
                dob_error_text.text("Required fields cannot be empty")
                dob_error_msg.show();
                dob_field.addClass("error");
                $("html, body").animate({scrollTop: dob_error_text.offset().top}, 'slow');

                return false;
            }

            return true;
        }

        function hideDateOfBirthValidationStatus() {
            var dob_error_msg = $("#dob_error");
            var dob_field = $("#dob_field");

            dob_error_msg.hide();
            dob_field.removeClass("error");
        }

        function showCountryValidationStatus() {
            var country = document.getElementById("country");
            var country_error = $("#country_error");
            var country_error_msg_text = $("#country_error_text");
            var country_field = $("#country_field");

            if (country != null && country.value == "" && country.required) {
                country_error_msg_text.text("Required fields cannot be empty")
                country_error.show();
                country_field.addClass("error");
                return false;
            }

            hideCountryValidationStatus();

            return true;
        }

        function hideCountryValidationStatus() {
            var country_error = $("#country_error");
            var country_field = $("#country_field");

            country_error.hide();
            country_field.removeClass("error");
        }

        function showMobileNumberValidationStatus() {
            var mobileNumber = document.getElementById("mobileNumber");
            var mobile_error_msg = $("#mobile_error");
            var mobile_error_msg_text = $("#mobile_error_text");
            var mobile_field = $("#mobile_field");

            if (mobileNumber != null && mobileNumber.value != null && mobileNumber.value.trim() !== ""){
                var mobilePattern = /^\s*(?:\+?(\d{1,3}))?[-. (]*(\d{3})?[-. )]*(\d{3})?[-. ]*(\d{4,6})(?: *x(\d+))?\s*$/;
                if (!mobilePattern.test(mobileNumber.value)) {
                    console.log("HITS");
                    mobile_error_msg_text.text("The format of the Mobile Number entered is incorrect."+
                        " Valid format is [+][country code][area code][local phone number]")
                    mobile_error_msg.show();
                    mobile_field.addClass("error");
                    $("html, body").animate({scrollTop: mobile_error_msg_text.offset().top}, 'slow');

                    return false;
                }
            }

            return true;
        }

        function hideMobileNumberValidationStatus() {
            var mobile_error_msg = $("#mobile_error");
            var mobile_field = $("#mobile_field");

            mobile_error_msg.hide();
            mobile_field.removeClass("error");
        }
    </script>
    <script src="libs/addons/calendar.min.js"></script>
</body>
</html>
