/*
 * Copyright 2016-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.drivers.utilities;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.tree.ConfigurationNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import static org.onlab.util.Tools.nullIsNotFound;

/**
 * Util CLass for Yang models.
 * Clean abstraction to read, obtain and populate
 * XML from Yang models translated into XML skeletons.
 */
public class YangXmlUtils {

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

    private static YangXmlUtils instance = null;

    //no instantiation, single instance.
    protected YangXmlUtils() {

    }

    /**
     * Retrieves a valid XML configuration for a specific XML path for a single
     * instance of the Map specified key-value pairs.
     *
     * @param file   path of the file to be used.
     * @param values map of key and values to set under the generic path.
     * @return Hierarchical configuration containing XML with values.
     */
    public XMLConfiguration getXmlConfiguration(String file, Map<String, String> values) {
        InputStream stream = getCfgInputStream(file);
        XMLConfiguration cfg = loadXml(stream);
        XMLConfiguration complete = new XMLConfiguration();
        List<String> paths = new ArrayList<>();
        Map<String, String> valuesWithKey = new HashMap<>();
        values.keySet().forEach(path -> {
            List<String> allPaths = findPaths(cfg, path);
            String key = nullIsNotFound(allPaths.isEmpty() ? null : allPaths.get(0),
                                        "Yang model does not contain desired path");
            paths.add(key);
            valuesWithKey.put(key, values.get(path));
        });
        Collections.sort(paths, new StringLengthComparator());
        paths.forEach(key -> complete.setProperty(key, valuesWithKey.get(key)));
        addProperties(cfg, complete);
        return complete;
    }


    /**
     * Retrieves a valid XML configuration for a specific XML path for multiple
     * instance of YangElements objects.
     *
     * @param file     path of the file to be used.
     * @param elements List of YangElements that are to be set.
     * @return Hierachical configuration containing XML with values.
     */
    public XMLConfiguration getXmlConfiguration(String file, List<YangElement> elements) {
        InputStream stream = getCfgInputStream(file);
        HierarchicalConfiguration cfg = loadXml(stream);
        XMLConfiguration complete = new XMLConfiguration();
        Multimap<String, YangElement> commonElements = ArrayListMultimap.create();

        //saves the elements in a Multimap based on the computed key.
        elements.forEach(element -> {
            String completeKey = nullIsNotFound(findPath(cfg, element.getBaseKey()),
                                                "Yang model does not contain desired path");
            commonElements.put(completeKey, element);
        });

        //iterates over the elements and constructs the configuration
        commonElements.keySet().forEach(key -> {
            // if there is more than one element for a given path
            if (commonElements.get(key).size() > 1) {
                //creates a list of nodes that have to be added for that specific path
                ArrayList<ConfigurationNode> nodes = new ArrayList<>();
                //creates the nodes
                commonElements.get(key).forEach(element -> nodes.add(getInnerNode(element).getRootNode()));
                //computes the parent path
                String parentPath = key.substring(0, key.lastIndexOf("."));
                //adds the nodes to the complete configuration
                complete.addNodes(parentPath, nodes);
            } else {
                //since there is only a single element we can assume it's the first one.
                Map<String, String> keysAndValues = commonElements.get(key).stream().
                        findFirst().get().getKeysAndValues();
                keysAndValues.forEach((k, v) -> complete.setProperty(key + "." + k, v));
            }
        });
        addProperties(cfg, complete);
        return complete;
    }

    //Adds all the properties of the original configuration to the new one.
    private void addProperties(HierarchicalConfiguration cfg, HierarchicalConfiguration complete) {
        cfg.getKeys().forEachRemaining(key -> {
            String property = (String) cfg.getProperty(key);
            if (!property.equals("")) {
                complete.setProperty(key, property);
            }
        });
    }

    protected InputStream getCfgInputStream(String file) {
        return getClass().getResourceAsStream(file);
    }

    /**
     * Reads a valid XML configuration and returns a Map containing XML field name.
     * and value contained for every subpath.
     *
     * @param cfg the Configuration to read.
     * @param path path of the information to be read.
     * @return list of elements containing baskey and map of key value pairs.
     */
    public List<YangElement> readXmlConfiguration(HierarchicalConfiguration cfg, String path) {
        List<YangElement> elements = new ArrayList<>();

        String key = nullIsNotFound(findPath(cfg, path), "Configuration does not contain desired path");

        getElements(cfg.configurationsAt(key), elements, key, cfg, path, key);
        return ImmutableList.copyOf(elements);
    }

    private void getElements(List<HierarchicalConfiguration> configurations,
                             List<YangElement> elements, String basekey,
                             HierarchicalConfiguration originalCfg, String path,
                             String originalKey) {
        //consider each sub configuration
        configurations.forEach(config -> {

            YangElement element = new YangElement(path, new HashMap<>());
            //for each of the keys of the sub configuration
            config.getKeys().forEachRemaining(key -> {
                //considers only one step ahead
                //if one step ahead has other steps calls self to analize them
                //else adds to yang element.
                if (key.split("\\.").length > 1) {
                    getElements(originalCfg.configurationsAt(basekey + "." + key.split("\\.")[0]),
                                elements, basekey + "." + key.split("\\.")[0], originalCfg, path,
                                originalKey);
                } else {
                    String replaced = basekey.replace(originalKey, "");
                    String partialKey = replaced.isEmpty() ? key : replaced.substring(1) + "." + key;
                    partialKey = partialKey.isEmpty() ? originalKey : partialKey;
                    //Adds values to the element with a subkey starting from the requeste path onwards
                    element.getKeysAndValues().put(partialKey, config.getProperty(key).toString());
                }
            });
            //if the element doesnt already exist
            if (!elements.contains(element) && !element.getKeysAndValues().isEmpty()) {
                elements.add(element);
            }
        });
    }

    /**
     * Single Instance of Yang utilities retriever.
     *
     * @return instance of YangXmlUtils
     */
    public static YangXmlUtils getInstance() {
        if (instance == null) {
            instance = new YangXmlUtils();
        }
        return instance;
    }

    /**
     * Return the string representation of the XMLConfig without header
     * and configuration element.
     *
     * @param cfg the XML to convert
     * @return the cfg string.
     */
    public String getString(XMLConfiguration cfg) {
        StringWriter stringWriter = new StringWriter();
        try {
            cfg.save(stringWriter);
        } catch (ConfigurationException e) {
            log.error("Cannot convert configuration", e.getMessage());
        }
        String xml = stringWriter.toString();
        xml = xml.substring(xml.indexOf("\n"));
        xml = xml.substring(xml.indexOf(">") + 1);
        return xml;
    }

    /**
     * Method to read an input stream into a XMLConfiguration.
     * @param xmlStream inputstream containing XML description
     * @return the XMLConfiguration object
     */
    public XMLConfiguration loadXml(InputStream xmlStream) {
        XMLConfiguration cfg = new XMLConfiguration();
        try {
            cfg.load(xmlStream);
            return cfg;
        } catch (ConfigurationException e) {
            throw new IllegalArgumentException("Cannot load xml from Stream", e);
        }
    }

    //Finds all paths for a corresponding element
    private List<String> findPaths(HierarchicalConfiguration cfg, String path) {
        List<String> paths = new ArrayList<>();
        cfg.getKeys().forEachRemaining(key -> {
            if (key.equals(path)) {
                paths.add(key);
            }
            if (key.contains("." + path)) {
                paths.add(key);
            }
        });
        return paths;
    }

    //Finds the first parent path corresponding to an element.
    private String findPath(HierarchicalConfiguration cfg, String element) {
        Iterator<String> it = cfg.getKeys();
        while (it.hasNext()) {
            String key = it.next();
            String[] arr = key.split("\\.");
            for (int i = 0; i < arr.length; i++) {
                if (element.equals(arr[i])) {
                    String completeKey = "";
                    for (int j = 0; j <= i; j++) {
                        completeKey = completeKey + "." + arr[j];
                    }
                    return completeKey.substring(1);
                }
            }
        }
        return null;
    }

    //creates a node based on a single Yang element.
    private HierarchicalConfiguration getInnerNode(YangElement element) {
        HierarchicalConfiguration node = new HierarchicalConfiguration();
        node.setRoot(new HierarchicalConfiguration.Node(element.getBaseKey()));
        element.getKeysAndValues().forEach(node::setProperty);
        return node;
    }

    //String lenght comparator
    private class StringLengthComparator implements Comparator<String> {

        public int compare(String o1, String o2) {
            if (o2 == null && o1 == null) {
                return 0;
            }

            if (o1 == null) {
                return o2.length();
            }

            if (o2 == null) {
                return o1.length();
            }

            if (o1.length() != o2.length()) {
                return o1.length() - o2.length(); //overflow impossible since lengths are non-negative
            }
            return o1.compareTo(o2);
        }
    }

}
