/*
 * 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.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.apache.sling.distribution.resources.impl.OsgiUtils;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Manager implementation which represents the distribution configurations as OSGI configuration.
 */
public class OsgiConfigurationManager implements DistributionConfigurationManager {
    private final ConfigurationAdmin configurationAdmin;
    private final Logger log = LoggerFactory.getLogger(getClass());

    private final DistributionComponentFactoryMap componentFactoryMap;

    public OsgiConfigurationManager(ConfigurationAdmin configurationAdmin, DistributionComponentFactoryMap componentFactoryMap) {

        this.configurationAdmin = configurationAdmin;
        this.componentFactoryMap = componentFactoryMap;
    }


    public List<DistributionConfiguration> getConfigs(ResourceResolver resolver, DistributionComponentKind kind) {
        List<Configuration> configurations = getOsgiConfigurations(kind, null);

        List<DistributionConfiguration> result = new ArrayList<DistributionConfiguration>();
        if (configurations == null || configurations.isEmpty()) {
            return result;
        }


        for (Configuration configuration : configurations) {
            Dictionary<String, Object> propertiesDict = configuration.getProperties();
            Map<String, Object> properties = OsgiUtils.fromDictionary(propertiesDict);

            properties = filterBeforeRead(properties);
            String name = PropertiesUtil.toString(properties.get(DistributionComponentConstants.PN_NAME), null);
            result.add(new DistributionConfiguration(kind, name, properties));

        }

        return result;
    }

    public DistributionConfiguration getConfig(ResourceResolver resolver, DistributionComponentKind kind, String name) {
        List<Configuration> configurations = getOsgiConfigurations(kind, name);

        if (configurations == null || configurations.isEmpty()) {
            return null;
        }

        if (configurations.size() > 1) {
            log.warn("Found more than one configuration of kind: {} and with name: {}",
                    kind.getName(), name);
        }

        Configuration configuration = configurations.get(0);

        if (configuration != null) {
            Dictionary<String, Object> properties = configuration.getProperties();
            Map<String, Object> result = OsgiUtils.fromDictionary(properties);

            String factoryPid = PropertiesUtil.toString(result.get(ConfigurationAdmin.SERVICE_FACTORYPID), null);
            String type = componentFactoryMap.getType(kind, factoryPid);

            result.put(DistributionComponentConstants.PN_TYPE, type);
            result = filterBeforeRead(result);
            return new DistributionConfiguration(kind, name, result);
        }

        return null;
    }

    public void saveConfig(ResourceResolver resolver, DistributionConfiguration config) {
        String componentName = config.getName();
        DistributionComponentKind componentKind = config.getKind();
        Map<String, Object> properties = config.getProperties();
        String componentType = PropertiesUtil.toString(properties.get(DistributionComponentConstants.PN_TYPE), null);

        if (componentKind == null || componentType == null) {
            throw new IllegalArgumentException("kind and type are required " + componentKind + componentType);
        }

        String factoryPid = componentFactoryMap.getFactoryPid(componentKind, componentType);
        if (factoryPid != null) {

            // SLING-5872 - Management of agent configurations must identify configurations by name
            // Remove the agents with the same name wich are not bind to the same factory.
            List<Configuration> configs = getOsgiConfigurations(componentKind, componentName);
            for (Iterator<Configuration> iter = configs.iterator() ; iter.hasNext() ; ) {
                Configuration conf = iter.next();
                if (factoryPid.equals(conf.getFactoryPid())) {
                    iter.remove();
                }
            }
            deleteOsgiConfigs(configs);

            properties.put(DistributionComponentConstants.PN_NAME, componentName);
            saveOsgiConfig(factoryPid, componentName, properties);
        }

    }

    public void deleteConfig(ResourceResolver resolver, DistributionComponentKind kind, String name) {
        List<Configuration> configs = getOsgiConfigurations(kind, name);

        deleteOsgiConfigs(configs);

        log.info("Delete component {}", name);

    }


    private void deleteOsgiConfigs(List<Configuration> configurations) {
        for (Configuration configuration : configurations) {
            String pid = configuration.getPid();

            try {
                configuration.delete();
                log.info("Deleted configuration {}", pid);
            } catch (IOException e) {
                log.warn("Cannot delete configuration {}", pid, e);
            }
        }
    }

    private List<Configuration> getOsgiConfigurations(DistributionComponentKind kind, String componentName) {
        List<String> factoryPids = componentFactoryMap.getFactoryPids(kind);

        List<Configuration> allConfigurations = new ArrayList<Configuration>();
        for (String factoryPid : factoryPids) {
            List<Configuration> configurations = getOsgiConfigurationsFromFactory(factoryPid, componentName);
            allConfigurations.addAll(configurations);
        }

        return allConfigurations;
    }


    private Configuration saveOsgiConfig(String factoryPid, String componentName, Map<String, Object> properties) {
        try {
            List<Configuration> configurations = getOsgiConfigurationsFromFactory(factoryPid, componentName);
            Configuration configuration = null;
            if (configurations == null || configurations.isEmpty()) {
                configuration = configurationAdmin.createFactoryConfiguration(factoryPid);
            } else {
                configuration = configurations.get(0);
            }

            properties = filterBeforeSave(properties);

            configuration.update(OsgiUtils.toDictionary(properties));

            return configuration;
        } catch (IOException e) {
            log.error("Cannot create configuration with factory {}", factoryPid, e);
        }

        return null;
    }

    private List<Configuration> getOsgiConfigurationsFromFactory(String factoryPid, String componentName) {
        List<Configuration> result = new ArrayList<Configuration>();

        try {
            String filter = OsgiUtils.getFilter(factoryPid, DistributionComponentConstants.PN_NAME, componentName);

            Configuration[] configurations = configurationAdmin.listConfigurations(filter);
            if (configurations != null) {
                result.addAll(Arrays.asList(configurations));
            }
        } catch (IOException e) {
            log.error("cannot get osgi configs", e);
        } catch (InvalidSyntaxException e) {
            log.error("cannot parse filter", e);
        }

        return result;
    }

    private Map<String, Object> filterBeforeSave(Map<String, Object> properties) {
        Map<String, Object> result = new HashMap<String, Object>();

        for (Map.Entry<String, Object> entry : properties.entrySet()) {
            if (entry.getKey().endsWith(".target")) {
                String entryValue = (String) entry.getValue();
                entryValue = packOsgiFilter(entryValue);
                if (entryValue != null) {
                    result.put(entry.getKey(), entryValue);
                }
            } else {
                result.put(entry.getKey(), entry.getValue());
            }

        }

        result = OsgiUtils.sanitize(result);
        return result;
    }

    private Map<String, Object> filterBeforeRead(Map<String, Object> properties) {
        Map<String, Object> result = new HashMap<String, Object>();

        for (Map.Entry<String, Object> entry : properties.entrySet()) {
            if (entry.getKey().endsWith(".target")) {
                String entryValue = (String) entry.getValue();
                entryValue = unpackOsgiFilter(entryValue);
                if (entryValue != null) {
                    result.put(entry.getKey(), entryValue);
                }
            } else {
                result.put(entry.getKey(), entry.getValue());
            }

        }

        result = OsgiUtils.sanitize(result);
        return result;
    }


    private String unpackOsgiFilter(String propertyValue) {

        String result = null;

        String namePattern = "\\(" + DistributionComponentConstants.PN_NAME + "=(.*?)\\)";

        Pattern r = Pattern.compile(namePattern);
        Matcher m = r.matcher(propertyValue);

        if (m.matches()) {
            result = m.group(1);
        }

        return result;
    }

    private String packOsgiFilter(String propertyValue) {
        return "(" + DistributionComponentConstants.PN_NAME + "=" + OsgiUtils.escape(propertyValue) + ")";
    }
}
