/*
 * 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.felix.configadmin.plugin.interpolation;

import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.ConfigurationPlugin;
import org.slf4j.Logger;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class InterpolationConfigurationPlugin implements ConfigurationPlugin {
    private static final String PREFIX = "$[";
    private static final String SUFFIX = "]";

    private static final String ENV_PREFIX = PREFIX + "env:";
    private static final Pattern ENV_PATTERN = createPattern(ENV_PREFIX);
    private static final String PROP_PREFIX = PREFIX + "prop:";
    private static final Pattern PROP_PATTERN = createPattern(PROP_PREFIX);
    private static final String SECRET_PREFIX = PREFIX + "secret:";
    private static final Pattern SECRET_PATTERN = createPattern(SECRET_PREFIX);

    private static Pattern createPattern(String prefix) {
        return Pattern.compile("\\Q" + prefix + "\\E.+?\\Q" + SUFFIX + "\\E");
    }

    private final BundleContext context;
    private final File directory;

    InterpolationConfigurationPlugin(BundleContext bc, String dir) {
        context = bc;
        if (dir != null) {
            directory = new File(dir);
            getLog().info("Configured directory for secrets: {}", dir);
        } else {
            directory = null;
        }
    }

    private Logger getLog() {
        return Activator.LOG;
    }

    @Override
    public void modifyConfiguration(ServiceReference<?> reference, Dictionary<String, Object> properties) {
        for (Enumeration<String> keys = properties.keys(); keys.hasMoreElements(); ) {
            String key = keys.nextElement();
            Object val = properties.get(key);
            if (val instanceof String) {
                String sv = (String) val;
                int idx = sv.indexOf(PREFIX);
                if (idx != -1) {
                    String varStart = sv.substring(idx);
                    Object pid = properties.get(Constants.SERVICE_PID);
                    Object newVal = null;
                    if (varStart.startsWith(SECRET_PREFIX)) {
                        newVal = replaceVariablesFromFile(key, sv, pid);
                    } else if (varStart.startsWith(ENV_PREFIX)) {
                        newVal = replaceVariablesFromEnvironment(key, sv, pid);
                    } else if (varStart.startsWith(PROP_PREFIX)) {
                        newVal = replaceVariablesFromProperties(key, sv, pid);
                    }

                    if (newVal != null)
                        properties.put(key, newVal);

                    getLog().info("Replaced value of configuration property '{}' for PID {}", key, pid);
                }
            }
        }
    }

    Object replaceVariablesFromEnvironment(final String key, final String value, final Object pid) {
        return replaceVariables(ENV_PREFIX, ENV_PATTERN, key, value, pid, n -> System.getenv(n));
    }

    Object replaceVariablesFromProperties(final String key, final String value, final Object pid) {
        return replaceVariables(PROP_PREFIX, PROP_PATTERN, key, value, pid, n -> context.getProperty(n));
    }

    Object replaceVariablesFromFile(final String key, final String value, final Object pid) {
        if (directory == null) {
            getLog().warn("Cannot replace property value {} for PID {}. No directory configured via framework property " +
                    Activator.DIR_PROPERTY, key, pid);
            return null;
        }

        return replaceVariables(SECRET_PREFIX, SECRET_PATTERN, key, value, pid, n -> {
            if (n.contains("..")) {
                getLog().error("Illegal secret location: " + n + " Going up in the directory structure is not allowed");
                return null;
            }

            File file = new File(directory, n);
            if (!file.isFile()) {
                getLog().warn("Cannot replace variable. Configured path is not a regular file: " + file);
                return null;
            }
            byte[] bytes;
            try {
                bytes = Files.readAllBytes(file.toPath());
            } catch (IOException e) {
                getLog().error("Problem replacing configuration property '{}' for PID {} from file {}",
                        key, pid, file, e);

                return null;
            }
            return new String(bytes).trim();
        });
    }

    Object replaceVariables(final String prefix, final Pattern pattern,
            final String key, final String value, final Object pid,
            final Function<String, String> valueSource) {
        final Matcher m = pattern.matcher(value);
        final StringBuffer sb = new StringBuffer();
        while (m.find()) {
            final String var = m.group();

            final int len = var.length();
            final String varName = var.substring(prefix.length(), len - SUFFIX.length());
            String replacement = valueSource.apply(varName);
            if (replacement != null)
                m.appendReplacement(sb, Matcher.quoteReplacement(replacement));
        }
        m.appendTail(sb);

        return sb.toString();
    }
}
