/*
 * 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.yangutils.linker.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

import org.onosproject.yangutils.datamodel.YangAtomicPath;
import org.onosproject.yangutils.datamodel.YangAugment;
import org.onosproject.yangutils.datamodel.YangAugmentableNode;
import org.onosproject.yangutils.datamodel.YangAugmentedInfo;
import org.onosproject.yangutils.datamodel.YangCase;
import org.onosproject.yangutils.datamodel.YangChoice;
import org.onosproject.yangutils.datamodel.YangImport;
import org.onosproject.yangutils.datamodel.YangInclude;
import org.onosproject.yangutils.datamodel.YangLeaf;
import org.onosproject.yangutils.datamodel.YangLeafList;
import org.onosproject.yangutils.datamodel.YangLeafRef;
import org.onosproject.yangutils.datamodel.YangLeavesHolder;
import org.onosproject.yangutils.datamodel.YangNode;
import org.onosproject.yangutils.datamodel.YangNodeIdentifier;
import org.onosproject.yangutils.datamodel.YangReferenceResolver;
import org.onosproject.yangutils.datamodel.utils.YangConstructType;
import org.onosproject.yangutils.linker.exceptions.LinkerException;

import static org.onosproject.yangutils.utils.UtilConstants.COLON;
import static org.onosproject.yangutils.utils.UtilConstants.EMPTY_STRING;

/**
 * Represent utilities for YANG linker.
 */
public final class YangLinkerUtils {

    private static final int IDENTIFIER_LENGTH = 64;
    private static final Pattern IDENTIFIER_PATTERN = Pattern.compile("[a-zA-Z_][a-zA-Z0-9_.-]*");
    private static final String XML = "xml";

    private YangLinkerUtils() {
    }

    /**
     * Detects collision between target nodes leaf/leaf-list or child node with augmented leaf/leaf-list or child node.
     *
     * @param targetNode target node
     * @param augment    augment node
     */
    private static void detectCollision(YangNode targetNode, YangAugment augment) {
        YangNode targetNodesChild = targetNode.getChild();
        YangNode augmentsChild = augment.getChild();
        YangNode parent = targetNode;
        if (targetNode instanceof YangAugment) {
            parent = targetNode.getParent();
        } else {
            while (parent.getParent() != null) {
                parent = parent.getParent();
            }
        }
        if (targetNode instanceof YangChoice) {
            //Do nothing
        } else {
            detectCollisionInLeaveHolders(targetNode, augment);
            while (augmentsChild != null) {
                detectCollisionInChildNodes(targetNodesChild, augmentsChild, targetNode.getName(), parent.getName());
                augmentsChild = augmentsChild.getNextSibling();
            }
        }
    }

    /*Detects collision between leaves/leaf-lists*/
    private static void detectCollisionInLeaveHolders(YangNode targetNode, YangAugment augment) {
        YangLeavesHolder targetNodesLeavesHolder = (YangLeavesHolder) targetNode;
        YangNode parent = targetNode;
        if (targetNode instanceof YangAugment) {
            parent = targetNode.getParent();
        } else {
            while (parent.getParent() != null) {
                parent = parent.getParent();
            }
        }
        if (augment.getListOfLeaf() != null && augment.getListOfLeaf().size() != 0
                && targetNodesLeavesHolder.getListOfLeaf() != null) {
            for (YangLeaf leaf : augment.getListOfLeaf()) {
                for (YangLeaf targetLeaf : targetNodesLeavesHolder.getListOfLeaf()) {
                    if (targetLeaf.getName().equals(leaf.getName())) {
                        throw new LinkerException("target node " + targetNode.getName()
                                + " contains augmented leaf " + leaf.getName() + " in module "
                                + parent.getName());
                    }
                }
            }
        } else if (augment.getListOfLeafList() != null
                && augment.getListOfLeafList().size() != 0
                && augment.getListOfLeafList() != null) {
            for (YangLeafList leafList : augment.getListOfLeafList()) {
                for (YangLeafList targetLeafList : targetNodesLeavesHolder.getListOfLeafList()) {
                    if (targetLeafList.getName().equals(leafList.getName())) {
                        throw new LinkerException("target node " + targetNode.getName()
                                + " contains augmented leaf-list" + leafList.getName() + " in module "
                                + parent.getName());
                    }
                }
            }
        }
    }

    /*Detects collision for child nodes.*/
    private static void detectCollisionInChildNodes(YangNode targetNodesChild, YangNode augmentsChild, String
            targetName, String parentName) {
        while (augmentsChild != null) {
            while (targetNodesChild != null) {
                if (targetNodesChild.getName().equals(augmentsChild.getName())) {
                    throw new LinkerException("target node " + targetName
                            + " contains augmented child node" + augmentsChild.getName() + " in module "
                            + parentName);
                }
                targetNodesChild = targetNodesChild.getNextSibling();
            }
            augmentsChild = augmentsChild.getNextSibling();
        }
    }

    /**
     * Detects collision between target nodes and its all leaf/leaf-list or child node with augmented leaf/leaf-list or
     * child node.
     *
     * @param targetNode target node
     * @param augment    augment node
     */
    static void detectCollisionForAugmentedNode(YangNode targetNode, YangAugment augment) {
        // Detect collision for target node and augment node.
        detectCollision(targetNode, augment);
        List<YangAugmentedInfo> yangAugmentedInfo = ((YangAugmentableNode) targetNode).getAugmentedInfoList();
        // Detect collision for target augment node and current augment node.
        for (YangAugmentedInfo info : yangAugmentedInfo) {
            detectCollision((YangAugment) info, augment);
        }
    }

    /**
     * Returns list of path names that are needed from augment.
     *
     * @param augment            instance of YANG augment
     * @param remainingAncestors ancestor count to move in augment path
     * @return list of path names needed in leafref
     */
    static List<String> getPathWithAugment(YangAugment augment, int remainingAncestors) {
        List<String> listOfPathName = new ArrayList<>();
        for (YangAtomicPath atomicPath : augment.getTargetNode()) {
            if (atomicPath.getNodeIdentifier().getPrefix() != null && !atomicPath.getNodeIdentifier().getPrefix()
                    .equals(EMPTY_STRING)) {
                listOfPathName.add(atomicPath.getNodeIdentifier().getPrefix() + ":" +
                        atomicPath.getNodeIdentifier().getName());
            } else {
                listOfPathName.add(atomicPath.getNodeIdentifier().getName());
            }
        }


        for (int countOfAncestor = 0; countOfAncestor < remainingAncestors; countOfAncestor++) {
            listOfPathName.remove(listOfPathName.size() - 1);
        }
        return listOfPathName;
    }

    /**
     * Skips the invalid nodes which cannot have data from YANG.
     *
     * @param currentParent current parent node reference
     * @param leafref       instance of YANG leafref
     * @return parent node which can hold data
     * @throws LinkerException a violation of linker rules
     */
    static YangNode skipInvalidDataNodes(YangNode currentParent, YangLeafRef leafref) throws LinkerException {
        while (currentParent instanceof YangChoice || currentParent instanceof YangCase) {
            if (currentParent.getParent() == null) {
                throw new LinkerException("YANG file error: The target node, in the leafref path " +
                        leafref.getPath() + ", is invalid.");
            }
            currentParent = currentParent.getParent();
        }
        return currentParent;
    }

    /**
     * Checks and return valid node identifier.
     *
     * @param nodeIdentifierString string from yang file
     * @param yangConstruct        yang construct for creating error message
     * @return valid node identifier
     */
    static YangNodeIdentifier getValidNodeIdentifier(String nodeIdentifierString,
                                                     YangConstructType yangConstruct) {
        String[] tmpData = nodeIdentifierString.split(Pattern.quote(COLON));
        if (tmpData.length == 1) {
            YangNodeIdentifier nodeIdentifier = new YangNodeIdentifier();
            nodeIdentifier.setName(getValidIdentifier(tmpData[0], yangConstruct));
            return nodeIdentifier;
        } else if (tmpData.length == 2) {
            YangNodeIdentifier nodeIdentifier = new YangNodeIdentifier();
            nodeIdentifier.setPrefix(getValidIdentifier(tmpData[0], yangConstruct));
            nodeIdentifier.setName(getValidIdentifier(tmpData[1], yangConstruct));
            return nodeIdentifier;
        } else {
            throw new LinkerException("YANG file error : " +
                    YangConstructType.getYangConstructType(yangConstruct) + " name " + nodeIdentifierString +
                    " is not valid.");
        }
    }

    /**
     * Validates identifier and returns concatenated string if string contains plus symbol.
     *
     * @param identifier    string from yang file
     * @param yangConstruct yang construct for creating error message=
     * @return concatenated string after removing double quotes
     */
    public static String getValidIdentifier(String identifier, YangConstructType yangConstruct) {

        if (identifier.length() > IDENTIFIER_LENGTH) {
            throw new LinkerException("YANG file error : " +
                    YangConstructType.getYangConstructType(yangConstruct) + " name " + identifier + " is " +
                    "greater than 64 characters.");
        } else if (!IDENTIFIER_PATTERN.matcher(identifier).matches()) {
            throw new LinkerException("YANG file error : " +
                    YangConstructType.getYangConstructType(yangConstruct) + " name " + identifier + " is not " +
                    "valid.");
        } else if (identifier.toLowerCase().startsWith(XML)) {
            throw new LinkerException("YANG file error : " +
                    YangConstructType.getYangConstructType(yangConstruct) + " identifier " + identifier +
                    " must not start with (('X'|'x') ('M'|'m') ('L'|'l')).");
        } else {
            return identifier;
        }
    }

    /**
     * Updates the priority for all the input files.
     *
     * @param yangNodeSet set of YANG files info
     */
    public static void updateFilePriority(Set<YangNode> yangNodeSet) {
        for (YangNode yangNode : yangNodeSet) {
            updateFilePriorityOfNode(yangNode);
        }
    }

    /**
     * Updates priority of the node.
     *
     * @param yangNode YANG node information
     */
    private static void updateFilePriorityOfNode(YangNode yangNode) {
        int curNodePriority = yangNode.getPriority();
        if (yangNode instanceof YangReferenceResolver) {
            List<YangImport> yangImportList = ((YangReferenceResolver) yangNode).getImportList();
            Iterator<YangImport> importInfoIterator = yangImportList.iterator();
            // Run through the imported list to update priority.
            while (importInfoIterator.hasNext()) {
                YangImport yangImport = importInfoIterator.next();
                YangNode importedNode = yangImport.getImportedNode();
                if (curNodePriority >= importedNode.getPriority()) {
                    importedNode.setPriority(curNodePriority + 1);
                    updateFilePriorityOfNode(importedNode);
                }
            }

            List<YangInclude> yangIncludeList = ((YangReferenceResolver) yangNode).getIncludeList();
            Iterator<YangInclude> includeInfoIterator = yangIncludeList.iterator();
            // Run through the imported list to update priority.
            while (includeInfoIterator.hasNext()) {
                YangInclude yangInclude = includeInfoIterator.next();
                YangNode includedNode = yangInclude.getIncludedNode();
                if (curNodePriority >= includedNode.getPriority()) {
                    includedNode.setPriority(curNodePriority + 1);
                    updateFilePriorityOfNode(includedNode);
                }
            }
        }
    }
}
