/*
 * Copyright 2015-present Open Networking Foundation
 *
 * 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
 *
 *     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.onosproject.cfg.impl;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import org.onlab.util.AbstractAccumulator;
import org.onlab.util.Accumulator;
import org.onlab.util.SharedExecutors;
import org.onosproject.cfg.ComponentConfigEvent;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.cfg.ComponentConfigStore;
import org.onosproject.cfg.ComponentConfigStoreDelegate;
import org.onosproject.cfg.ConfigProperty;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger;

import java.io.IOException;
import java.io.InputStream;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.security.AppGuard.checkPermission;
import static org.onosproject.security.AppPermission.Type.CONFIG_READ;
import static org.onosproject.security.AppPermission.Type.CONFIG_WRITE;
import static org.slf4j.LoggerFactory.getLogger;


/**
 * Implementation of the centralized component configuration service.
 */
@Component(immediate = true, service = ComponentConfigService.class)
public class ComponentConfigManager implements ComponentConfigService {

    private static final String COMPONENT_NULL = "Component name cannot be null";
    private static final String PROPERTY_NULL = "Property name cannot be null";
    private static final String COMPONENT_MISSING = "Component %s is not registered";
    private static final String PROPERTY_MISSING = "Property %s does not exist for %s";


    //Symbolic constants for use with the accumulator
    private static final int MAX_ITEMS = 100;
    private static final int MAX_BATCH_MILLIS = 1000;
    private static final int MAX_IDLE_MILLIS = 250;

    private static final String RESOURCE_EXT = ".cfgdef";

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

    private final ComponentConfigStoreDelegate delegate = new InternalStoreDelegate();
    private final InternalAccumulator accumulator = new InternalAccumulator();

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected ComponentConfigStore store;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected ConfigurationAdmin cfgAdmin;

    // Locally maintained catalog of definitions.
    private final Map<String, Map<String, ConfigProperty>> properties =
            Maps.newConcurrentMap();


    @Activate
    public void activate() {
        store.setDelegate(delegate);
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        store.unsetDelegate(delegate);
        log.info("Stopped");
    }

    @Override
    public Set<String> getComponentNames() {
        checkPermission(CONFIG_READ);
        return ImmutableSet.copyOf(properties.keySet());
    }

    @Override
    public void registerProperties(Class<?> componentClass) {
        checkPermission(CONFIG_WRITE);

        String componentName = componentClass.getName();
        String resourceName = componentClass.getSimpleName() + RESOURCE_EXT;
        if (componentClass.getResource(resourceName) == null) {
            // Try looking in my/package/name/MyClass.cfgdef
            resourceName = componentClass.getCanonicalName().replace('.', '/') + RESOURCE_EXT;
        }
        try (InputStream ris = componentClass.getResourceAsStream(resourceName)) {
            checkArgument(ris != null, "Property definitions not found at resource %s",
                          resourceName);

            // Read the definitions
            Set<ConfigProperty> defs = ConfigPropertyDefinitions.read(ris);

            // Produce a new map of the properties and register it.
            Map<String, ConfigProperty> map = Maps.newConcurrentMap();
            defs.forEach(p -> map.put(p.name(), p));

            properties.put(componentName, map);
            loadExistingValues(componentName, map);
        } catch (IOException e) {
            log.error("Unable to read property definitions from resource " + resourceName, e);
        }
    }

    @Override
    public void unregisterProperties(Class<?> componentClass, boolean clear) {
        checkPermission(CONFIG_WRITE);

        String componentName = componentClass.getName();
        checkNotNull(componentName, COMPONENT_NULL);
        Map<String, ConfigProperty> cps = properties.remove(componentName);
        if (clear && cps != null) {
            cps.keySet().forEach(name -> store.unsetProperty(componentName, name));
            clearExistingValues(componentName);
        }
    }

    // Clears any existing values that may have been set.
    private void clearExistingValues(String componentName) {
        triggerUpdate(componentName);
    }

    @Override
    public Set<ConfigProperty> getProperties(String componentName) {
        checkPermission(CONFIG_READ);

        Map<String, ConfigProperty> map = properties.get(componentName);
        return map != null ? ImmutableSet.copyOf(map.values()) : null;
    }

    @Override
    public void setProperty(String componentName, String name, String value) {
        checkPermission(CONFIG_WRITE);

        checkNotNull(componentName, COMPONENT_NULL);
        checkNotNull(name, PROPERTY_NULL);

        checkArgument(properties.containsKey(componentName),
                      COMPONENT_MISSING, componentName);
        checkArgument(properties.get(componentName).containsKey(name),
                      PROPERTY_MISSING, name, componentName);
        checkValidity(componentName, name, value);
        store.setProperty(componentName, name, value);
    }

    @Override
    public void preSetProperty(String componentName, String name, String value) {
        preSetProperty(componentName, name, value, true);
    }

    @Override
    public void preSetProperty(String componentName, String name, String value, boolean override) {
        checkPermission(CONFIG_WRITE);

        checkNotNull(componentName, COMPONENT_NULL);
        checkNotNull(name, PROPERTY_NULL);
        checkValidity(componentName, name, value);
        store.setProperty(componentName, name, value, override);
    }

    @Override
    public void unsetProperty(String componentName, String name) {
        checkPermission(CONFIG_WRITE);

        checkNotNull(componentName, COMPONENT_NULL);
        checkNotNull(name, PROPERTY_NULL);

        checkArgument(properties.containsKey(componentName),
                      COMPONENT_MISSING, componentName);
        checkArgument(properties.get(componentName).containsKey(name),
                      PROPERTY_MISSING, name, componentName);
        store.unsetProperty(componentName, name);
    }

    @Override
    public ConfigProperty getProperty(String componentName, String attribute) {
        checkPermission(CONFIG_READ);

        Map<String, ConfigProperty> map = properties.get(componentName);
        if (map != null) {
            return map.get(attribute);
        } else {
            log.error("Attribute {} not present in component {}", attribute, componentName);
            return null;
        }
    }

    private class InternalStoreDelegate implements ComponentConfigStoreDelegate {

        @Override
        public void notify(ComponentConfigEvent event) {
            String componentName = event.subject();
            String name = event.name();
            String value = event.value();

            switch (event.type()) {
                case PROPERTY_SET:
                    set(componentName, name, value);
                    break;
                case PROPERTY_UNSET:
                    reset(componentName, name);
                    break;
                default:
                    break;
            }
        }
    }

    // Buffers multiple subsequent configuration updates into one notification.
    private class InternalAccumulator extends AbstractAccumulator<String>
            implements Accumulator<String> {

        protected InternalAccumulator() {
            super(SharedExecutors.getTimer(), MAX_ITEMS, MAX_BATCH_MILLIS, MAX_IDLE_MILLIS);
        }

        @Override
        public void processItems(List<String> items) {
            // Conversion to set removes duplicates
            Set<String> componentSet = new HashSet<>(items);
            componentSet.forEach(ComponentConfigManager.this::triggerUpdate);
        }
    }

    // Locates the property in the component map and replaces it with an
    // updated copy.
    private void set(String componentName, String name, String value) {
        Map<String, ConfigProperty> map = properties.get(componentName);
        if (map != null) {
            ConfigProperty prop = map.get(name);
            if (prop != null) {
                map.put(name, ConfigProperty.setProperty(prop, value));
                accumulator.add(componentName);
                return;
            }
        }

        // If definition doesn't exist in local catalog, cache the property.
        preSet(componentName, name, value);
    }

    // Locates the property in the component map and replaces it with an
    // reset copy.
    private void reset(String componentName, String name) {
        Map<String, ConfigProperty> map = properties.get(componentName);
        if (map != null) {
            ConfigProperty prop = map.get(name);
            if (prop != null) {
                map.put(name, ConfigProperty.resetProperty(prop));
                accumulator.add(componentName);
                return;
            }
            log.warn("Unable to reset non-existent property {} for component {}",
                     name, componentName);
        }
    }

    // Stores non-existent property so that loadExistingValues() can load in future.
    private void preSet(String componentName, String name, String value) {
        try {
            Configuration config = cfgAdmin.getConfiguration(componentName, null);
            Dictionary<String, Object> props = config.getProperties();
            if (props == null) {
                props = new Hashtable<>();
            }
            props.put(name, value);
            config.update(props);
        } catch (IOException e) {
            log.error("Failed to preset configuration for {}", componentName);
        }
    }

    // Checks whether the value of the specified configuration property is a valid one or not.
    private void checkValidity(String componentName, String name, String newValue) {
        Map<String, ConfigProperty> map = properties.get(componentName);
        if (map == null) {
            return;
        }
        ConfigProperty prop = map.get(name);
        ConfigProperty.Type type = prop.type();
        try {
            switch (type) {
                case INTEGER:
                    Integer.parseInt(newValue);
                    break;
                case LONG:
                    Long.parseLong(newValue);
                    break;
                case FLOAT:
                    Float.parseFloat(newValue);
                    break;
                case DOUBLE:
                    Double.parseDouble(newValue);
                    break;
                case BOOLEAN:
                    if (!((newValue != null) && (newValue.equalsIgnoreCase("true") ||
                            newValue.equalsIgnoreCase("false")))) {
                        throw new IllegalArgumentException("Invalid " + type + " value");
                    }
                    break;
                case STRING:
                case BYTE:
                    //do nothing
                    break;
                default:
                    log.warn("Not a valid config property type");
                    break;

            }
        } catch (NumberFormatException e) {
            throw new NumberFormatException("Invalid " + type + " value");
        }
    }

    // Loads existing property values that may have been learned from other
    // nodes in the cluster before the local property registration.
    private void loadExistingValues(String componentName,
                                    Map<String, ConfigProperty> map) {
        try {
            Configuration cfg = cfgAdmin.getConfiguration(componentName, null);
            Dictionary<String, Object> localProperties = cfg.getProperties();

            // Iterate over all registered config properties...
            for (ConfigProperty p : ImmutableSet.copyOf(map.values())) {
                String name = p.name();
                String globalValue = store.getProperty(componentName, name);
                String localValue = localProperties != null ? (String) localProperties.get(name) : null;

                log.debug("Processing {} property {}; global {}; local {}",
                          componentName, name, globalValue, localValue);
                try {
                    // 1) If the global value is the same as default, or
                    // 2) if it is not set explicitly, but the local value is
                    // not the same as the default, reset local value to default.
                    if (Objects.equals(globalValue, p.defaultValue()) ||
                            (globalValue == null &&
                                    !Objects.equals(localValue, p.defaultValue()))) {
                        log.debug("Resetting {} property {}; value same as default",
                                  componentName, name);
                        reset(componentName, name);

                    } else if (!Objects.equals(globalValue, localValue)) {
                        // If the local value is different from global value
                        // validate the global value and apply it locally.
                        String newValue;
                        if (globalValue != null) {
                            newValue = globalValue;
                        } else {
                            newValue = localValue;
                        }
                        log.debug("Setting {} property {} to {}",
                                  componentName, name, newValue);
                        checkValidity(componentName, name, newValue);
                        set(componentName, name, newValue);

                    } else {
                        // Otherwise, simply update the registered property
                        // with the global value.
                        log.debug("Syncing {} property {} to {}",
                                  componentName, name, globalValue);
                        map.put(name, ConfigProperty.setProperty(p, globalValue));
                    }
                } catch (IllegalArgumentException e) {
                    log.warn("Value {} for property {} is not a valid {}; using default",
                             globalValue, name, p.type());
                    reset(componentName, name);
                }
            }
        } catch (IOException e) {
            log.error("Unable to get configuration for " + componentName, e);
        }
    }

    private void triggerUpdate(String componentName) {
        try {
            Configuration cfg = cfgAdmin.getConfiguration(componentName, null);
            Map<String, ConfigProperty> map = properties.get(componentName);
            if (map == null) {
                //  Prevent NPE if the component isn't there
                log.warn("Component not found for " + componentName);
                return;
            }
            Dictionary<String, Object> props = new Hashtable<>();
            map.values().stream().filter(p -> p.value() != null)
                    .forEach(p -> props.put(p.name(), p.value()));
            cfg.update(props);
        } catch (IOException e) {
            log.warn("Unable to update configuration for " + componentName, e);
        }
    }
}
