/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.nifi.stateless.config;

import org.apache.nifi.stateless.engine.StatelessEngineConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PropertiesFileEngineConfigurationParser {
    private static final Logger logger = LoggerFactory.getLogger(PropertiesFileEngineConfigurationParser.class);
    private static final String PREFIX = "nifi.stateless.";

    private static final String NAR_DIRECTORY = PREFIX + "nar.directory";
    private static final String EXTENSIONS_DIRECTORY = PREFIX + "extensions.directory";
    private static final String WORKING_DIRECTORY = PREFIX + "working.directory";
    private static final String CONTENT_REPO_DIRECTORY = PREFIX + "content.repository.directory";

    private static final String TRUSTSTORE_FILE = PREFIX + "security.truststore";
    private static final String TRUSTSTORE_TYPE = PREFIX + "security.truststoreType";
    private static final String TRUSTSTORE_PASSWORD = PREFIX + "security.truststorePasswd";
    private static final String KEYSTORE_FILE = PREFIX + "security.keystore";
    private static final String KEYSTORE_TYPE = PREFIX + "security.keystoreType";
    private static final String KEYSTORE_PASSWORD = PREFIX + "security.keystorePasswd";
    private static final String KEY_PASSWORD = PREFIX + "security.keyPasswd";

    private static final String SENSITIVE_PROPS_KEY = PREFIX + "sensitive.props.key";
    private static final String KRB5_FILE = PREFIX + "kerberos.krb5.file";

    private static final String DEFAULT_KRB5_FILENAME = "/etc/krb5.conf";
    private static final String DEFAULT_ENCRYPTION_PASSWORD = "nifi-stateless";

    private static final Pattern EXTENSION_CLIENT_PATTERN = Pattern.compile("\\Qnifi.stateless.extension.client.\\E(.*?)\\.(.+)");


    public StatelessEngineConfiguration parseEngineConfiguration(final File propertiesFile) throws IOException, StatelessConfigurationException {
        if (!propertiesFile.exists()) {
            throw new FileNotFoundException("Could not find properties file " + propertiesFile.getAbsolutePath());
        }

        final Properties properties = new Properties();
        try (final InputStream in = new FileInputStream(propertiesFile)) {
            properties.load(in);
        }

        final File narDirectory = new File(getRequired(properties, NAR_DIRECTORY));
        if (!narDirectory.exists()) {
            throw new StatelessConfigurationException("NAR Directory " + narDirectory.getAbsolutePath() + " specified in properties file does not exist");
        }

        final File workingDirectory = new File(getRequired(properties, WORKING_DIRECTORY));
        if (!workingDirectory.exists() && !workingDirectory.mkdirs()) {
            throw new StatelessConfigurationException("Working Directory " + workingDirectory.getAbsolutePath() + " specified in properties file does not exist and could not be created");
        }

        final String extensionsDirectoryFilename = properties.getProperty(EXTENSIONS_DIRECTORY);
        final File extensionsDirectory = extensionsDirectoryFilename == null ? narDirectory : new File(extensionsDirectoryFilename);
        if (!extensionsDirectory.exists() && !extensionsDirectory.mkdirs()) {
            throw new StatelessConfigurationException("Extensions Directory " + narDirectory.getAbsolutePath() + " specified in properties file does not exist and could not be created");
        }

        final String contentRepoDirectoryFilename = properties.getProperty(CONTENT_REPO_DIRECTORY, "");
        final File contentRepoDirectory = contentRepoDirectoryFilename.isEmpty() ? null : new File(contentRepoDirectoryFilename);

        final String krb5Filename = properties.getProperty(KRB5_FILE, DEFAULT_KRB5_FILENAME);
        final File krb5File = new File(krb5Filename);

        final String sensitivePropsKey = properties.getProperty(SENSITIVE_PROPS_KEY, DEFAULT_ENCRYPTION_PASSWORD);
        final SslContextDefinition sslContextDefinition = parseSslContextDefinition(properties);

        final List<ExtensionClientDefinition> extensionClients = parseExtensionClients(properties);

        return new StatelessEngineConfiguration() {
            @Override
            public File getWorkingDirectory() {
                return workingDirectory;
            }

            @Override
            public File getNarDirectory() {
                return narDirectory;
            }

            @Override
            public File getExtensionsDirectory() {
                return extensionsDirectory;
            }

            @Override
            public File getKrb5File() {
                return krb5File;
            }

            @Override
            public Optional<File> getContentRepositoryDirectory() {
                return Optional.ofNullable(contentRepoDirectory);
            }

            @Override
            public SslContextDefinition getSslContext() {
                return sslContextDefinition;
            }

            @Override
            public String getSensitivePropsKey() {
                return sensitivePropsKey;
            }

            @Override
            public List<ExtensionClientDefinition> getExtensionClients() {
                return extensionClients;
            }
        };
    }

    private List<ExtensionClientDefinition> parseExtensionClients(final Properties properties) {
        final Map<String, ExtensionClientDefinition> extensionClientDefinitions = new LinkedHashMap<>();

        for (final String propertyName : properties.stringPropertyNames()) {
            final Matcher matcher = EXTENSION_CLIENT_PATTERN.matcher(propertyName);
            if (!matcher.matches()) {
                continue;
            }

            // For a property name like:
            // nifi.stateless.extension.client.c1.type=nexus
            // We consider 'c1' the <client key> and 'type' the <relative property name>
            final String clientKey = matcher.group(1);
            final ExtensionClientDefinition definition = extensionClientDefinitions.computeIfAbsent(clientKey, key -> new ExtensionClientDefinition());
            final String relativePropertyName = matcher.group(2);
            final String propertyValue = properties.getProperty(propertyName);

            switch (relativePropertyName) {
                case "type":
                    definition.setExtensionClientType(propertyValue);
                    break;
                case "baseUrl":
                    definition.setBaseUrl(propertyValue);
                    break;
                case "timeout":
                    definition.setCommsTimeout(propertyValue);
                    break;
                case "useSslContext":
                    definition.setUseSslContext(Boolean.parseBoolean(propertyValue));
                    break;
                default:
                    logger.warn("Encountered invalid property: <{}>. Will ignore this property.", propertyName);
                    break;
            }

        }

        return new ArrayList<>(extensionClientDefinitions.values());
    }

    private SslContextDefinition parseSslContextDefinition(final Properties properties) {
        final String truststoreFile = properties.getProperty(TRUSTSTORE_FILE);
        if (truststoreFile == null || truststoreFile.trim().isEmpty()) {
            return null;
        }

        final SslContextDefinition sslContextDefinition;
        sslContextDefinition = new SslContextDefinition();
        sslContextDefinition.setTruststoreFile(truststoreFile);
        sslContextDefinition.setTruststorePass(properties.getProperty(TRUSTSTORE_PASSWORD));
        sslContextDefinition.setTruststoreType(properties.getProperty(TRUSTSTORE_TYPE));

        final String keystoreFile = properties.getProperty(KEYSTORE_FILE);
        if (keystoreFile != null && !keystoreFile.trim().isEmpty()) {
            sslContextDefinition.setKeystoreFile(keystoreFile);
            sslContextDefinition.setKeystoreType(properties.getProperty(KEYSTORE_TYPE));

            final String keystorePass = properties.getProperty(KEYSTORE_PASSWORD);
            sslContextDefinition.setKeystorePass(keystorePass);

            final String explicitKeyPass = properties.getProperty(KEY_PASSWORD);
            final String keyPass = (explicitKeyPass == null || explicitKeyPass.trim().isEmpty()) ? keystorePass : explicitKeyPass;
            sslContextDefinition.setKeyPass(keyPass);
        }

        return sslContextDefinition;
    }

    private String getRequired(final Properties properties, final String key) throws StatelessConfigurationException {
        final String propertyValue = properties.getProperty(key);
        if (propertyValue == null || propertyValue.trim().isEmpty()) {
            throw new StatelessConfigurationException("Properties file is missing required property " + key);
        }

        return propertyValue.trim();
    }

}
