/*
 * 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.sling.distribution.component.impl;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.osgi.service.cm.ConfigurationAdmin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * {@link org.apache.sling.distribution.component.impl.DistributionConfigurationManager} implementation based on OSGI configs.
 * For each tree of properties a set of OSGI configs is generated and registered in ConfigurationAdmin.
 * To delete a component all configs owned by that component will be unregistered from ConfigurationAdmin.
 */
@Component
@Service(DistributionConfigurationManager.class)
public class DefaultDistributionConfigurationManager implements DistributionConfigurationManager {

    @Property(label = "Resource Config Enabled", description = "If storing config in resource tree is enabled.", boolValue = false)
    public static final String CONFIG_ENABLED = "resource.config.enabled";

    @Property(label = "Resource Config Prefix", description = "The prefix of properties to be stored in content", value = "etc.")
    public static final String CONFIG_PREFIX = "resource.config.prefix";

    @Property(label = "Resource Config Root", description = "The resource config root", value = "/etc/distribution")
    public static final String CONFIG_ROOT = "resource.config.root";

    @Property(label = "Resource Config Properties", description = "The resource config properties", value = {"enabled"})
    public static final String CONFIG_PROPERTIES = "resource.config.properties";

    @Property(label = "Resource Config Defaults", description = "The default values for resource config properties", value = {"serializationType=distribution"})
    public static final String CONFIG_DEFAULTS = "resource.config.defaults";

    @Reference
    ConfigurationAdmin configurationAdmin;

    @Reference
    private DistributionComponentFactoryMap componentFactoryMap;

    private DistributionConfigurationManager osgiManager;
    private DistributionConfigurationManager resourceManager;

    static String resourcePrefix;
    static final String OSGI_PREFIX = "";

    private final Logger log = LoggerFactory.getLogger(getClass());

    @Activate
    void activate(Map<String, Object> properties) {
        boolean configEnabled = PropertiesUtil.toBoolean(properties.get(CONFIG_ENABLED), false);

        String configRoot = SettingsUtils.removeEmptyEntry(PropertiesUtil.toString(properties.get(CONFIG_ROOT), null));
        resourcePrefix = SettingsUtils.removeEmptyEntry(PropertiesUtil.toString(properties.get(CONFIG_PREFIX), null));

        String[] configProperties = SettingsUtils.removeEmptyEntries(PropertiesUtil.toStringArray(properties.get(CONFIG_PROPERTIES), null));

        if (configEnabled && configRoot != null && configProperties != null) {
            Map<String, String> configDefaults = PropertiesUtil.toMap(properties.get(CONFIG_DEFAULTS), new String[0]);

            resourceManager = new ResourceConfigurationManager(configRoot, configProperties, configDefaults);
        }

        osgiManager = new OsgiConfigurationManager(configurationAdmin, componentFactoryMap);
    }

    @Deactivate
    void deactivate() {
        resourceManager = null;
        osgiManager = null;
    }


    @Override
    public List<DistributionConfiguration> getConfigs(ResourceResolver resolver, DistributionComponentKind kind) {
        List<DistributionConfiguration> result = osgiManager.getConfigs(resolver, kind);

        if (resourceManager != null) {
            List<DistributionConfiguration> resourceConfigs = resourceManager.getConfigs(resolver, kind);
            result = mergeConfigs(result, resourceConfigs, resourcePrefix);
        }

        return result;
    }

    @Override
    public DistributionConfiguration getConfig(ResourceResolver resolver, DistributionComponentKind kind, String name) {

        DistributionConfiguration resultConfig = osgiManager.getConfig(resolver, kind, name);

        if (resourceManager != null) {
            DistributionConfiguration resourceConfig = resourceManager.getConfig(resolver, kind, name);
            resultConfig = mergeConfig(resultConfig, resourceConfig, resourcePrefix);
        }

        return resultConfig;
    }

    @Override
    public void saveConfig(ResourceResolver resolver, DistributionConfiguration config) {
        log.debug("saving config {}", config);

        if (resourceManager != null) {
            Map<String, DistributionConfiguration> splitConfig = splitConfig(config, resourcePrefix);

            DistributionConfiguration defaultConfig = splitConfig.get(OSGI_PREFIX);

            osgiManager.saveConfig(resolver, defaultConfig);

            DistributionConfiguration resourceConfig = splitConfig.get(resourcePrefix);
            log.debug("retrieved config {}", resourceConfig);

            if (resourceConfig != null) {
                resourceManager.saveConfig(resolver, resourceConfig);
                log.debug("saved resource config: {}", resourceConfig);
            }
        } else {
            osgiManager.saveConfig(resolver, config);
            log.debug("saved osgi config: {}", config);
        }
    }

    @Override
    public void deleteConfig(ResourceResolver resolver, DistributionComponentKind kind, String name) {
        osgiManager.deleteConfig(resolver, kind, name);

        if (resourceManager != null) {
            resourceManager.deleteConfig(resolver, kind, name);
        }
    }

    static DistributionConfiguration mergeConfig(DistributionConfiguration main, DistributionConfiguration extension, String prefix) {

        if (main == null) {
            return null;
        }

        Map<String, DistributionConfiguration> configMap = new HashMap<String, DistributionConfiguration>();

        configMap.put(OSGI_PREFIX, main);
        configMap.put(prefix, extension);

        return mergeConfig(main.getKind(), main.getName(), configMap);
    }

    static DistributionConfiguration mergeConfig(DistributionComponentKind kind, String name, Map<String, DistributionConfiguration> configMap) {
        Map<String, Object> result = new HashMap<String, Object>();
        for (String prefixKey : configMap.keySet()) {
            DistributionConfiguration config = configMap.get(prefixKey);
            if (config == null) {
                continue;
            }
            Map<String, Object> properties = config.getProperties();

            if (prefixKey.equals(OSGI_PREFIX)) {
                result.putAll(properties);
            } else {
                for (String propertyKey : properties.keySet()) {
                    Object propertyValue = properties.get(propertyKey);
                    result.put(prefixKey + propertyKey, propertyValue);
                }
            }
        }

        return new DistributionConfiguration(kind, name, result);
    }

    static List<DistributionConfiguration> mergeConfigs(List<DistributionConfiguration> target, List<DistributionConfiguration> source, String prefix) {
        List<DistributionConfiguration> result = new ArrayList<DistributionConfiguration>();

        Map<String, DistributionConfiguration> sourceMap = new HashMap<String, DistributionConfiguration>();
        for (DistributionConfiguration config : source) {
            sourceMap.put(config.getName(), config);
        }

        for (DistributionConfiguration targetConfig : target) {
            DistributionConfiguration sourceConfig = sourceMap.get(targetConfig.getName());

            DistributionConfiguration mergedConfig = mergeConfig(targetConfig, sourceConfig, prefix);

            result.add(mergedConfig);
        }

        return result;
    }

    /**
     * Split a {@link DistributionConfiguration} into two configurations, so that properties starting with a certain prefix
     * go to a separate configuration while the remaining ones will live in a new configuration
     * @param config a configuration
     * @param prefix a prefix
     * @return a {@link Map} of prefix -> configuration
     */
    private static Map<String, DistributionConfiguration> splitConfig(DistributionConfiguration config, String prefix) {
        Map<String, Object> distributionConfigurationProperties = config.getProperties();

        // properties for OSGi configuration
        Map<String, Object> defaultMap = new HashMap<String, Object>();

        // properties for resource configuration
        Map<String, Object> prefixMap = new HashMap<String, Object>();

        // split the properties of the given configuration between the OSGi config and the persisted config
        for (String configurationPropertyKey : distributionConfigurationProperties.keySet()) {
            if (configurationPropertyKey.startsWith(prefix)) {
                prefixMap.put(configurationPropertyKey.substring(prefix.length()), distributionConfigurationProperties.get(configurationPropertyKey));
            } else {
                defaultMap.put(configurationPropertyKey, distributionConfigurationProperties.get(configurationPropertyKey));
            }
        }

        // create an OSGi and a persisted configuration
        Map<String, DistributionConfiguration> result = new HashMap<String, DistributionConfiguration>();
        result.put(OSGI_PREFIX, new DistributionConfiguration(config.getKind(), config.getName(), defaultMap));
        if (prefixMap.size() > 0) {
            result.put(prefix, new DistributionConfiguration(config.getKind(), config.getName(), prefixMap));
        }

        return result;
    }
}
