/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2023 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.validators;

import org.jboss.installer.core.InstallationData;
import org.jboss.installer.core.LanguageUtils;
import org.jboss.installer.core.ValidationResult;
import org.jboss.installer.postinstall.task.AbstractHttpsEnableConfig;
import org.wildfly.security.ssl.CipherSuiteSelector;

import java.nio.file.Path;

import static org.jboss.installer.screens.AbstractSSLSecurityScreen.CIPHER_NAMES_LABEL_KEY;
import static org.jboss.installer.screens.AbstractSSLSecurityScreen.CIPHER_SUITES_LABEL_KEY;
import static org.jboss.installer.screens.AbstractSSLSecurityScreen.PROTOCOLS_LABEL_KEY;

public class SSLSecurityValidator {

    public static final String INVALID_CIPHER_SUITE_NAME = "ssl.config.invalid_cipher_suite_name_error";
    private static final String ERROR_EMPTY_FIELD_KEY = "generic.validation.empty_field";

    private final LanguageUtils langUtils;
    private final String keystorePrefix;
    private final String truststorePrefix;

    public SSLSecurityValidator(LanguageUtils langUtils, String keystorePrefix, String truststorePrefix) {
            this.langUtils = langUtils;
        this.keystorePrefix = keystorePrefix;
        this.truststorePrefix = truststorePrefix;
    }

    public ValidationResult validate(AbstractHttpsEnableConfig config, InstallationData installationData) {
        if (config.isDoGenerateStore()) {
            // DN  ... nothing to validate atm
            // validity must be an integer greater than 0 or empty (default, i.e. 90)
            if (config.getValidity() != null && config.getValidity().length() > 0) {
                final ValidationResult validityResult = new IntRangeValidator(langUtils, 1).validate(config.getValidity());
                if (validityResult.getResult() == ValidationResult.Result.ERROR) {
                    return validityResult;
                }
            }
            if (config.isMutual()) {
                // client cert path file must exist
                final ValidationResult clientCertResult = new FileValidator(langUtils).validate(Path.of(config.getClientCertPath()));
                if (clientCertResult.getResult() != ValidationResult.Result.OK) {
                    return clientCertResult;
                }
            }
        } else {
            // configure an existing key-store
            KeystoreCredentialsValidator ksValidator = new KeystoreCredentialsValidator(langUtils, keystorePrefix);
            final ValidationResult keyStoreResult = ksValidator.validate(config.getKeyStorePath(), config.getKeyStorePassword(), installationData.getTargetFolder());
            if (keyStoreResult.getResult() != ValidationResult.Result.OK) {
                return keyStoreResult;
            }
            if (config.isMutual()) {
                // trust-store file must exist
                ksValidator = new KeystoreCredentialsValidator(langUtils, truststorePrefix);
                final ValidationResult trustStoreResult = ksValidator.validate(config.getTrustStorePath(), config.getTrustStorePassword(), installationData.getTargetFolder());
                if (trustStoreResult.getResult() != ValidationResult.Result.OK) {
                    return trustStoreResult;
                }
            }
        }
        // protocols
        if (config.getProtocols() != null) {
            if (config.getProtocols().isEmpty()) {
                return ValidationResult.error(langUtils.getString(ERROR_EMPTY_FIELD_KEY, langUtils.getString(PROTOCOLS_LABEL_KEY)));
            }
        }

        // cipher suites
        if (config.getCipherSuites() != null) {
            if (config.getCipherSuites().length() > 0) {
                try {
                    // PROTOCOL_TLSv12 and below
                    CipherSuiteSelector.fromString(config.getCipherSuites());
                } catch (IllegalArgumentException e) {
                    return ValidationResult.error(langUtils.getString(INVALID_CIPHER_SUITE_NAME, e.getMessage()));
                }
            } else {
                return ValidationResult.error(langUtils.getString(ERROR_EMPTY_FIELD_KEY, langUtils.getString(CIPHER_SUITES_LABEL_KEY)));
            }
        }

        if (config.getTls13cipherNames() != null) {
            if (config.getTls13cipherNames().length() > 0) {
                try {
                    CipherSuiteSelector.fromNamesString(config.getTls13cipherNames());
                } catch (IllegalArgumentException e) {
                    return ValidationResult.error(langUtils.getString(INVALID_CIPHER_SUITE_NAME, e.getMessage()));
                }
            } else {
                return ValidationResult.error(langUtils.getString(ERROR_EMPTY_FIELD_KEY, langUtils.getString(CIPHER_NAMES_LABEL_KEY)));
            }
        }
        return ValidationResult.ok();
    }
}
