/**
 * 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
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * 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.winegrower.service;

import static java.util.Collections.list;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toMap;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.winegrower.lang.Substitutor;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;

public class DefaultConfigurationAdmin implements ConfigurationAdmin {

    private final static String WINEGROWER_CONFIG_PATH = "winegrower.config.path";
    private final static String WINEGROWER_CONFIG_EXTENSION = ".cfg";

    private final Map<String, String> providedConfiguration;
    private final Map<String, Configuration> configurations = new HashMap<>();

    public DefaultConfigurationAdmin(final Map<String, String> providedConfiguration) {
        this.providedConfiguration = providedConfiguration;
    }

    public Map<String, String> getProvidedConfiguration() {
        return providedConfiguration;
    }

    @Override
    public Configuration createFactoryConfiguration(final String pid) {
        return new DefaultConfiguration(providedConfiguration, pid, null, null);
    }

    @Override
    public Configuration createFactoryConfiguration(final String pid, final String location) {
        return new DefaultConfiguration(providedConfiguration, pid, null, location);
    }

    @Override
    public Configuration getConfiguration(final String pid, final String location) {
        return configurations.computeIfAbsent(pid, p -> new DefaultConfiguration(providedConfiguration, null, p, location));
    }

    @Override
    public Configuration getConfiguration(final String pid) {
        return configurations.computeIfAbsent(pid, p -> new DefaultConfiguration(providedConfiguration, null, p, null));
    }

    @Override
    public Configuration[] listConfigurations(final String filter) {
        try {
            final Filter predicate = filter == null ? null : FrameworkUtil.createFilter(filter);
            return configurations.values().stream()
                    .filter(it -> predicate == null || predicate.match(it.getProperties()))
                    .toArray(Configuration[]::new);
        } catch (final InvalidSyntaxException e) {
            throw new IllegalArgumentException(e);
        }
    }

    private static class DefaultConfiguration implements Configuration {
        private final String factoryPid;
        private final String pid;
        private final Map<String, String> defaultConfig = new HashMap<>();
        private final File defaultExternalConfigLocation;
        private final Map<String, String> configRegistry;
        private String location;
        private final Hashtable<String, Object> properties;
        private final AtomicLong changeCount = new AtomicLong();

        private DefaultConfiguration(final Map<String, String> configRegistry,
                                     final String factoryPid, final String pid, final String location) {
            this.configRegistry = configRegistry;
            this.factoryPid = factoryPid;
            this.pid = pid;
            this.location = location;
            this.properties = new Hashtable<>();
            this.defaultExternalConfigLocation = new File(
                    // support a cascade of known "homes"
                    System.getProperty(WINEGROWER_CONFIG_PATH,
                            System.getProperty("karaf.base",
                                    System.getProperty("catalina.base",
                                            System.getProperty("karaf.home",
                                                    System.getProperty("karaf.etc"))))),
                    pid + WINEGROWER_CONFIG_EXTENSION);
            loadConfig(pid);

        }

        private void loadConfig(final String pid) {
            final String prefix = "winegrower.service." + pid + "."; // for "global" registries like system props

            // we first read the config from the classpath (lowest priority)
            try (final InputStream embedConfig = Thread.currentThread().getContextClassLoader()
                                                       .getResourceAsStream(pid + WINEGROWER_CONFIG_EXTENSION)) {
                if (embedConfig != null) {
                    defaultConfig.putAll(load(embedConfig));
                }
            } catch (final IOException e) {
                throw new IllegalArgumentException(e);
            }
            properties.putAll(defaultConfig);

            // then the default registry which is considered "in JVM" so less prioritized than external config
            configRegistry.entrySet().stream()
                          .filter(it -> it.getKey().startsWith(prefix))
                          .forEach(entry -> properties.put(entry.getKey().substring(prefix.length()), entry.getValue()));

            // then from an external file
            if (defaultExternalConfigLocation.isFile()) {
                try (final InputStream stream = new FileInputStream(defaultExternalConfigLocation)) {
                    this.properties.putAll(load(stream));
                } catch (final IOException e) {
                    throw new IllegalArgumentException(e);
                }
            }

            // and finally from system properties
            System.getProperties().stringPropertyNames().stream()
                  .filter(it -> it.startsWith(prefix))
                  .forEach(key -> properties.put(key.substring(prefix.length()), System.getProperty(key)));
        }

        @Override
        public String getPid() {
            return pid;
        }

        @Override
        public Dictionary<String, Object> getProperties() {
            return properties;
        }

        @Override
        public void update(final Dictionary<String, ?> properties) {
            this.properties.clear();
            loadConfig(pid);
            this.properties.putAll(converter(properties));
            this.changeCount.incrementAndGet();
        }

        @Override
        public void delete() {
            // no-op
        }

        @Override
        public String getFactoryPid() {
            return factoryPid;
        }

        @Override
        public void update() {
            update(new Hashtable<>());
            if (defaultExternalConfigLocation.isFile()) {
                final Properties output = new Properties();
                output.putAll(properties);
                try (final OutputStream outputStream = new FileOutputStream(defaultExternalConfigLocation)) {
                    output.store(outputStream, "Updated configuration on " + new Date());
                } catch (final IOException e) {
                    throw new IllegalArgumentException(e);
                }
            } // else: don't modify neither the classpath nor system properties - this would be insane even if doable
            this.changeCount.incrementAndGet();
        }

        @Override
        public void setBundleLocation(final String location) {
            this.location = location;
        }

        @Override
        public String getBundleLocation() {
            return location;
        }

        @Override
        public long getChangeCount() {
            return changeCount.get();
        }

        private Map<String, String> converter(final Dictionary<String, ?> properties) {
            return list(properties.keys()).stream().collect(toMap(identity(), it -> properties.get(it).toString()));
        }

        private Map<String, String> load(final InputStream stream) {
            final Properties properties = new Properties();
            try {
                properties.load(stream);
            } catch (final IOException e) {
                throw new IllegalArgumentException(e);
            }
            final Map<String, String> placeholders = new HashMap<>(Map.class.cast(properties));
            placeholders.putAll(Map.class.cast(System.getProperties()));
            final Substitutor substitutor = new Substitutor(placeholders);
            return properties.stringPropertyNames().stream()
                .collect(toMap(
                    identity(),
                    it -> it.contains("${") && it.contains("}") ? substitutor.replace(it) : properties.getProperty(it)));
        }
    }
}
