/**
 * 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 org.apache.winegrower.lang.Substitutor;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.ConfigurationEvent;
import org.osgi.service.cm.ConfigurationListener;

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.Collection;
import java.util.Date;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;

import static java.util.Arrays.asList;
import static java.util.Collections.list;
import static java.util.Locale.ROOT;
import static java.util.Optional.ofNullable;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toMap;

public abstract 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<Key, Configuration> configurations = new HashMap<>();

    private final Collection<ConfigurationListener> configurationListeners;

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

    public void preload(final List<String> names) {
        if (names == null || names.isEmpty()) {
            return;
        }
        names.forEach(it -> getConfiguration(it).setBundleLocation(null));
    }

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

    @Override
    public Configuration getFactoryConfiguration(final String factoryPid, final String name, final String location) {
        return getOrCreate(factoryPid, null, location, name);
    }

    @Override
    public Configuration getFactoryConfiguration(final String factoryPid, final String name) {
        return getOrCreate(factoryPid, null, null, name);
    }

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

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

    @Override
    public Configuration getConfiguration(final String pid, final String location) {
        return getOrCreate(null, pid, location, null);
    }

    @Override
    public Configuration getConfiguration(final String pid) {
        return getConfiguration(pid, 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 Configuration getOrCreate(final String factoryPid, final String pid, final String location,
                                      final String name) {
        final Key key = new Key(factoryPid, pid);
        final Configuration existing = configurations.get(key);
        if (existing != null) {
            return existing;
        }
        final DefaultConfiguration created = new DefaultConfiguration(providedConfiguration,
                factoryPid, pid, location, name) {
            @Override
            public void setBundleLocation(final String location) {
                super.setBundleLocation(location);
                final ConfigurationEvent event = new ConfigurationEvent(
                        getSelfReference(), ConfigurationEvent.CM_LOCATION_CHANGED, factoryPid, pid);
                configurationListeners.forEach(it -> it.configurationEvent(event));
            }

            @Override
            public void update(Dictionary<String, ?> properties) {
                super.update(properties);
                final ConfigurationEvent event = new ConfigurationEvent(
                        getSelfReference(), ConfigurationEvent.CM_UPDATED, factoryPid, pid);
                configurationListeners.forEach(it -> it.configurationEvent(event));
            }

            @Override
            public void delete() {
                super.delete();
                final ConfigurationEvent event = new ConfigurationEvent(
                        getSelfReference(), ConfigurationEvent.CM_DELETED, factoryPid, pid);
                configurationListeners.forEach(it -> it.configurationEvent(event));
            }
        };
        configurations.putIfAbsent(key, created);
        return created;
    }

    protected abstract ServiceReference<ConfigurationAdmin> getSelfReference();

    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 final String name;

        private String location;

        private final Hashtable<String, Object> properties;

        private final AtomicLong changeCount = new AtomicLong();

        private final Set<ConfigurationAttribute> attributes = new HashSet<>();

        private DefaultConfiguration(final Map<String, String> configRegistry, final String factoryPid, final String pid,
                final String location, final String name) {
            this.configRegistry = configRegistry;
            this.factoryPid = factoryPid;
            this.pid = pid;
            this.location = location;
            this.name = name;
            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 and env variables
            // (env is for the machine so less precise than system props so set first)
            final String envPrefix = prefix.toUpperCase(ROOT).replace('.', '_');
            System.getenv().keySet().stream()
                    .filter(it -> it.length() > prefix.length() && envPrefix.equalsIgnoreCase(it.substring(0, envPrefix.length())))
                    .forEach(key -> {
                        final String k = key.substring(envPrefix.length());
                        // env keys loose the case so in case it is important, enable to force the key name
                        // ex: to set configuration{pid=a.b.c, key=fooBar, value=dummy} you would set:
                        //     A_B_C_FOOBAR_NAME=fooBar
                        //     A_B_C_FOOBAR=dummy
                        // note that the FOOBAR in the key is not important, previous config is the same than:
                        //     A_B_C_1_NAME=fooBar
                        //     A_B_C_1=dummy
                        // but when there key is not ambiguous (all lowercase) it is simpler to set (key=foobar):
                        //     A_B_C_FOOBAR=dummy
                        properties.put(
                                ofNullable(System.getenv(key + "_NAME")).orElseGet(() -> k.toLowerCase(ROOT)),
                                System.getenv(key));
                    });

            System.getProperties().stringPropertyNames().stream()
                    .filter(it -> it.startsWith(prefix))
                    .forEach(key -> properties.put(key.substring(prefix.length()), System.getProperty(key)));


            // ensure the factoryPid/pid is there if exists
            ofNullable(pid).ifPresent(v -> properties.putIfAbsent("service.pid", v));
            ofNullable(factoryPid).ifPresent(v -> properties.putIfAbsent("service.factoryPid", v));
            ofNullable(name).ifPresent(v -> properties.putIfAbsent("name", v));
        }

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

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

        @Override
        public Dictionary<String, Object> getProcessedProperties(final ServiceReference<?> reference) {
            return reference.getProperties();
        }

        @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 boolean updateIfDifferent(final Dictionary<String, ?> properties) {
            if (properties == null || list(properties.keys()).stream()
                    .anyMatch(it -> !properties.get(it).equals(this.properties.get(it)))) {
                update(properties);
                return true;
            }
            return false;
        }

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

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

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

        @Override
        public void addAttributes(final ConfigurationAttribute... attrs) {
            ofNullable(attrs).ifPresent(values -> attributes.addAll(asList(attrs)));
        }

        @Override
        public Set<ConfigurationAttribute> getAttributes() {
            return attributes;
        }

        @Override
        public void removeAttributes(ConfigurationAttribute... attrs) throws IOException {
            ofNullable(attrs).ifPresent(values -> attributes.removeAll(asList(attrs)));
        }

        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)));
        }
    }

    private static class Key {

        private final String factoryPid;

        private final String pid;

        private final int hash;

        private Key(final String factoryPid, final String pid) {
            this.factoryPid = factoryPid;
            this.pid = pid;
            this.hash = Objects.hash(factoryPid, pid);
        }

        @Override
        public boolean equals(final Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            final Key key = Key.class.cast(o);
            return Objects.equals(factoryPid, key.factoryPid) && Objects.equals(pid, key.pid);
        }

        @Override
        public int hashCode() {
            return hash;
        }

        @Override
        public String toString() {
            return "Key{factoryPid='" + factoryPid + "', pid='" + pid + "'}";
        }
    }
}
