/**
 * 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.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
            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 + "'}";
        }
    }
}
