/*
 * Copyright 2015-present Open Networking Laboratory
 *
 * 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.net.config.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Maps;
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.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onosproject.net.config.BasicNetworkConfigService;
import org.onosproject.net.config.Config;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;

/**
 * Component for loading the initial network configuration.
 */
@Component(immediate = true)
public class NetworkConfigLoader {

    private static final File CFG_FILE = new File("../config/network-cfg.json");

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

    // Dependency to ensure the basic subject factories are properly initialized
    // before we start loading configs from file
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected BasicNetworkConfigService basicConfigs;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected NetworkConfigService networkConfigService;

    // FIXME: Add mutual exclusion to make sure this happens only once per startup.

    private final Map<InnerConfigPosition, JsonNode> jsons = Maps.newConcurrentMap();

    private final NetworkConfigListener configListener = new InnerConfigListener();

    private ObjectNode root;

    @Activate
    public void activate() {
        //TODO Maybe this should be at the bottom to avoid a potential race
        networkConfigService.addListener(configListener);
        try {
            if (CFG_FILE.exists()) {
                root = (ObjectNode) new ObjectMapper().readTree(CFG_FILE);

                populateConfigurations();

                applyConfigurations();

                log.info("Loaded initial network configuration from {}", CFG_FILE);
            }
        } catch (Exception e) {
            log.warn("Unable to load initial network configuration from {}",
                    CFG_FILE, e);
        }
    }

    @Deactivate
    public void deactivate() {
        networkConfigService.removeListener(configListener);
    }
    // sweep through pending config jsons and try to add them

    /**
     * Inner class that allows for handling of newly added NetConfig types.
     */
    private final class InnerConfigListener implements NetworkConfigListener {

        @Override
        public void event(NetworkConfigEvent event) {
            //TODO should this be done for other types of NetworkConfigEvents?
            if (event.type() == NetworkConfigEvent.Type.CONFIG_REGISTERED ||
                    event.type() == NetworkConfigEvent.Type.CONFIG_ADDED) {
                applyConfigurations();
            }

        }
    }

    /**
     * Inner class that allows for tracking of JSON class configurations.
     */
    private final class InnerConfigPosition {
        private final String subjectKey, subject, configKey;

        private String subjectKey() {
            return subjectKey;
        }

        private String subject() {
            return subject;
        }

        private String configKey() {
            return configKey;
        }

        private InnerConfigPosition(String subjectKey, String subject, String configKey) {
            this.subjectKey = subjectKey;
            this.subject = subject;
            this.configKey = configKey;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj instanceof InnerConfigPosition) {
                final InnerConfigPosition that = (InnerConfigPosition) obj;
                return Objects.equals(this.subjectKey, that.subjectKey)
                        && Objects.equals(this.subject, that.subject)
                        && Objects.equals(this.configKey, that.configKey);
            }
            return false;
        }

        @Override
        public int hashCode() {
            return Objects.hash(subjectKey, subject, configKey);
        }
    }

    /**
     * Save the JSON leaves associated with a specific subject key.
     *
     * @param sk   the subject key string.
     * @param node the node associated with the subject key.
     */
    private void saveJson(String sk, ObjectNode node) {
        node.fieldNames().forEachRemaining(s ->
                saveSubjectJson(sk, s, (ObjectNode) node.path(s)));
    }

    /**
     * Save the JSON leaves of the tree rooted as the node 'node' with subject key 'sk'.
     *
     * @param sk   the string of the subject key.
     * @param s    the subject name.
     * @param node the node rooting this subtree.
     */
    private void saveSubjectJson(String sk,
                                 String s, ObjectNode node) {
        node.fieldNames().forEachRemaining(c ->
                this.jsons.put(new InnerConfigPosition(sk, s, c), node.path(c)));
    }

    /**
     * Iterate through the JSON and populate a list of the leaf nodes of the structure.
     */
    private void populateConfigurations() {
        root.fieldNames().forEachRemaining(sk ->
                saveJson(sk, (ObjectNode) root.path(sk)));

    }

    /**
     * Apply the configurations associated with all of the config classes that
     * are imported and have not yet been applied.
     */
    private void applyConfigurations() {
        Iterator<Map.Entry<InnerConfigPosition, JsonNode>> iter = jsons.entrySet().iterator();

        Map.Entry<InnerConfigPosition, JsonNode> entry;
        InnerConfigPosition key;
        JsonNode node;
        String subjectKey;
        String subjectString;
        String configKey;

        while (iter.hasNext()) {
            entry = iter.next();
            node = entry.getValue();
            key = entry.getKey();
            subjectKey = key.subjectKey();
            subjectString = key.subject();
            configKey = key.configKey();

            Class<? extends Config> configClass =
                    networkConfigService.getConfigClass(subjectKey, configKey);
            //Check that the config class has been imported
            if (configClass != null) {

                Object subject = networkConfigService.getSubjectFactory(subjectKey).
                        createSubject(subjectString);

                //Apply the configuration
                networkConfigService.applyConfig(subject, configClass, node);

                //Now that it has been applied the corresponding JSON entry is no longer needed
                iter.remove();
            }
        }
    }

}
