/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2022 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jboss.installer.screens.domain;

import org.apache.commons.lang3.StringUtils;
import org.jboss.installer.common.FileChooserPanel;
import org.jboss.installer.common.UiResources;
import org.jboss.installer.core.LanguageUtils;
import org.jboss.installer.core.MnemonicUtils;
import org.jboss.installer.postinstall.task.secdom.KerberosSecurity;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.stream.Collectors;

import static javax.swing.JFileChooser.FILES_ONLY;
import static org.jboss.installer.common.UiResources.createFieldLabelWithColonSuffix;
import static org.jboss.installer.common.UiResources.createTextField;
import static org.jboss.installer.common.UiResources.setTooltip;

public class KerberosSecurityDomainPanel extends JPanel {

    public static final String KERBEROS_SECURITY_FACTORY_NAME_LABEL = "security_domain_screen.kerberos.kerberos.security.factory.name.label";
    public static final String PRINCIPAL_LABEL = "security_domain_screen.kerberos.principal.label";
    public static final String KEYTAB_PATH_LABEL = "security_domain_screen.kerberos.keytab.path.label";
    public static final String MECHANISM_NAMES_LABEL = "security_domain_screen.kerberos.mechanism.names.label";
    public static final String MECHANISM_OIDS_LABEL = "security_domain_screen.kerberos.mechanism.oids.label";
    public static final String KRB5_CONF_FILE_LABEL = "security_domain_screen.kerberos.krb5.conf.file.label";
    public static final String FILESYSTEM_REALM_NAME_LABEL = "security_domain_screen.kerberos.filesystem.realm.name.label";
    public static final String FILESYSTEM_REALM_PATH_LABEL = "security_domain_screen.kerberos.filesystem.realm.path.label";
    public static final String IDENTITY_NAME_LABEL = "security_domain_screen.kerberos.identity.name.label";
    public static final String IDENTITY_ATTRIBUTE_NAME_LABEL = "security_domain_screen.kerberos.identity.attribute.name.label";
    public static final String IDENTITY_ATTRIBUTE_VALUE_LABEL = "security_domain_screen.kerberos.identity.attribute.value.label";
    public static final String SIMPLE_ROLE_DECODER_NAME_LABEL = "security_domain_screen.kerberos.simple.role.decoder.name.label";
    public static final String SIMPLE_ROLE_DECODER_ATTRIBUTE_LABEL = "security_domain_screen.kerberos.simple.role.decoder.attribute.label";

    private final LanguageUtils langUtils;
    private final Path baseFolder;

    private final JTextField kerberosSecurityFactoryField = createTextField("krbSF");
    private final JTextField principalField = createTextField("HTTP/host@REALM");
    private final MnemonicUtils mnemonicUtils;
    private FileChooserPanel keyTabPathField;
    private final JTextField mechanismNamesField = createTextField("KRB5, SPNEGO");
    private final JTextField mechanismOidsField = createTextField("1.2.840.113554.1.2.2, 1.3.6.1.5.5.2");
    private FileChooserPanel krb5ConfField;
    private final JTextField fileSystemRealmNameField = createTextField("exampleFsRealm");
    private final JTextField fileSystemRealmPathField =  createTextField("fs-realm-users");
    private final JTextField identityNameField = createTextField("user1@REALM");
    private final JTextField identityAttributeNameField = createTextField("Roles");
    private final JTextField identityAttributeValueField = createTextField("Admin, Guest");
    private final JTextField simpleRoleDecoderNameField = createTextField("from-roles-attribute");
    private final JTextField simpleRoleDecoderAttributeField = createTextField("Roles");

    public KerberosSecurityDomainPanel(LanguageUtils langUtils, Path baseFolder, MnemonicUtils mnemonicUtils) {
        this.langUtils = langUtils;
        this.setLayout(new GridBagLayout());
        this.baseFolder = baseFolder;
        this.mnemonicUtils = mnemonicUtils;
        initUI();
    }

    private void initUI() {
        this.setBorder(UiResources.spacedBorder());
        GridBagConstraints c = UiResources.initializeConstraints();
        c.insets = new Insets(5, 0, 0, 0);

        addField(c, KERBEROS_SECURITY_FACTORY_NAME_LABEL, kerberosSecurityFactoryField);
        addField(c, PRINCIPAL_LABEL, principalField);
        c.gridy++;
        c.gridwidth = 2;
        final JLabel keyTabPathLabel = createFieldLabelWithColonSuffix(langUtils.getString(KEYTAB_PATH_LABEL));
        this.add(keyTabPathLabel, c);
        c.gridy++;
        keyTabPathField = FileChooserPanel.builder(langUtils, FILES_ONLY, mnemonicUtils).build();
        this.add(keyTabPathField, c);
        setTooltip(keyTabPathLabel, langUtils.getString(KEYTAB_PATH_LABEL + ".tooltip"));
        setTooltip(keyTabPathField, langUtils.getString(KEYTAB_PATH_LABEL + ".tooltip"));

        c.gridwidth = 1;
        addField(c, MECHANISM_NAMES_LABEL, mechanismNamesField);
        addField(c, MECHANISM_OIDS_LABEL, mechanismOidsField);

        c.gridy++;
        c.gridwidth = 2;
        final JLabel krb5ConfLabel = createFieldLabelWithColonSuffix(langUtils.getString(KRB5_CONF_FILE_LABEL));
        this.add(krb5ConfLabel, c);
        c.gridy++;
        krb5ConfField = FileChooserPanel.builder(langUtils, FILES_ONLY, mnemonicUtils).build();
        this.add(krb5ConfField, c);
        setTooltip(krb5ConfLabel, langUtils.getString(KRB5_CONF_FILE_LABEL + ".tooltip"));
        setTooltip(krb5ConfField, langUtils.getString(KRB5_CONF_FILE_LABEL + ".tooltip"));

        c.gridy++;
        c.gridwidth = 1;
        addField(c, FILESYSTEM_REALM_NAME_LABEL, fileSystemRealmNameField);
        c.gridy++;
        addField(c, FILESYSTEM_REALM_PATH_LABEL, fileSystemRealmPathField);

        addField(c, IDENTITY_NAME_LABEL, identityNameField);
        addField(c, IDENTITY_ATTRIBUTE_NAME_LABEL, identityAttributeNameField);
        addField(c, IDENTITY_ATTRIBUTE_VALUE_LABEL, identityAttributeValueField);
        addField(c, SIMPLE_ROLE_DECODER_NAME_LABEL, simpleRoleDecoderNameField);
        addField(c, SIMPLE_ROLE_DECODER_ATTRIBUTE_LABEL, simpleRoleDecoderAttributeField);
    }

    public void addField(GridBagConstraints c, String labelKey, JComponent comp) {
        UiResources.addField(this, c, langUtils.getString(labelKey),
                langUtils.getString(labelKey + ".tooltip"), comp);
    }

    KerberosSecurity.KerberosConfig getConfig() throws FileChooserPanel.InvalidPathException {
        final KerberosSecurity.KerberosConfig kerberosConfig = new KerberosSecurity.KerberosConfig();
        kerberosConfig.setKerberosSecurityFactoryName(UiResources.readTextValue(kerberosSecurityFactoryField));
        kerberosConfig.setPrincipal(UiResources.readTextValue(principalField));
        kerberosConfig.setKeyTabPath(keyTabPathField.getText()==null?null:Paths.get(keyTabPathField.asPath()));
        kerberosConfig.setMechanismNames(Arrays.stream(mechanismNamesField.getText().split(","))
                .map(String::trim)
                .filter(StringUtils::isNotEmpty)
                .collect(Collectors.toList())
                .toArray(new String[]{}));
        kerberosConfig.setMechanismOids(Arrays.stream(mechanismOidsField.getText().split(","))
                .map(String::trim)
                .filter(StringUtils::isNotEmpty)
                .collect(Collectors.toList())
                .toArray(new String[]{}));
        kerberosConfig.setKrb5Conf(krb5ConfField.getText()==null?null:Paths.get(krb5ConfField.asPath()));
        kerberosConfig.setFileSystemRealmName(UiResources.readTextValue(fileSystemRealmNameField));
        kerberosConfig.setFileSystemRealmPath(UiResources.readTextValue(fileSystemRealmPathField));
        kerberosConfig.setFileSystemRealmStandalonePath(Paths.get(baseFolder + File.separator + "standalone" + File.separator + "configuration" + File.separator + fileSystemRealmPathField.getText()));
        kerberosConfig.setFileSystemRealmDomainPath(Paths.get(baseFolder + File.separator + "domain" + File.separator + "configuration" + File.separator + fileSystemRealmPathField.getText()));
        kerberosConfig.setIdentityName(UiResources.readTextValue(identityNameField));
        kerberosConfig.setIdentityAttributeName(UiResources.readTextValue(identityAttributeNameField));
        kerberosConfig.setIdentityAttributeValue(Arrays.stream(identityAttributeValueField.getText().split(","))
                .map(String::trim)
                .filter(StringUtils::isNotEmpty)
                .collect(Collectors.toList())
                .toArray(new String[]{}));
        kerberosConfig.setSimpleRoleDecoderName(UiResources.readTextValue(simpleRoleDecoderNameField));
        kerberosConfig.setSimpleRoleDecoderAttribute(UiResources.readTextValue(simpleRoleDecoderAttributeField));
        return kerberosConfig;
    }
}
