/*
 * 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.parser.impl.parserutils;

import java.util.ArrayList;
import java.util.List;

import org.onosproject.yangutils.datamodel.CollisionDetector;
import org.onosproject.yangutils.datamodel.YangModule;
import org.onosproject.yangutils.datamodel.YangNode;
import org.onosproject.yangutils.datamodel.YangNodeIdentifier;
import org.onosproject.yangutils.datamodel.YangSubModule;
import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
import org.onosproject.yangutils.parser.Parsable;
import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser;
import org.onosproject.yangutils.parser.exceptions.ParserException;
import org.onosproject.yangutils.parser.impl.TreeWalkListener;

import static org.onosproject.yangutils.translator.tojava.utils.JavaIdentifierSyntax.getCapitalCase;
import static org.onosproject.yangutils.utils.YangConstructType.AUGMENT_DATA;

/**
 * Represents a utility which provides listener utilities augment node.
 */
public final class AugmentListenerUtil {

    /**
     * Prefix to be added to generated java file for augment node.
     */
    private static final String AUGMENTED = "Augmented";

    /**
     * The number of time augment has updated the same target node in same module/submodule.
     */
    private static int occurrenceCount = 1;

    /**
     * List of names for augment's generated java file.
     */
    private static List<String> augmentJavaFileNameList = new ArrayList<>();

    private static final int ONE = 1;
    private static final int TWO = 2;
    private static final int ZERO = 0;

    /**
     * Creates an instance of augment java file name generator utility.
     */
    private AugmentListenerUtil() {
    }

    /**
     * Sets the augment java file name list.
     *
     * @param nameList name list
     */
    private static void setAugmentJavaFileNameList(List<String> nameList) {
        augmentJavaFileNameList = nameList;
    }

    /**
     * Returns augment java file name list.
     *
     * @return augment java file name list
     */
    public static List<String> getAugmentJavaFileNameList() {
        return augmentJavaFileNameList;
    }

    /**
     * Sets occurrence count.
     *
     * @param occurrence occurrence count
     */
    private static void setOccurrenceCount(int occurrence) {
        occurrenceCount = occurrence;
    }

    /**
     * Returns occurrence count.
     *
     * @return occurrence count
     */
    private static int getOccurrenceCount() {
        return occurrenceCount;
    }

    /**
     * Generates name for augment node also detects collision for java file generation of augment node when
     * augment is updating the same target node in same parent multiple times.
     *
     * @param curData parsable data
     * @param targetNodes list of target nodes
     * @param listener tree walk listener
     * @return name for augment node
     */
    public static String generateNameForAugmentNode(Parsable curData, List<YangNodeIdentifier> targetNodes,
            TreeWalkListener listener) {

        String curPrefix = getParentsPrefix((YangNode) curData);
        YangNodeIdentifier nodeId = targetNodes.get(targetNodes.size() - 1);
        boolean isPrefix = isPrefixPresent(nodeId, curPrefix);
        String generateName = createValidNameForAugment(nodeId, isPrefix);

        if (listener.getParsedDataStack().peek() instanceof CollisionDetector) {
            try {
                ((CollisionDetector) listener.getParsedDataStack().peek()).detectCollidingChild(generateName,
                        AUGMENT_DATA);
            } catch (DataModelException e) {
                return updateNameWhenHasMultipleOuccrrence(nodeId, isPrefix);
            }
        }

        clearOccurrenceCount();
        return generateName;
    }

    /**
     * Creates a name identifier for augment.
     *
     * @param nodeId node identifier
     * @param isPrefix if prefix is present or it is not equals to parent's prefix
     * @return valid name for augment
     */
    public static String createValidNameForAugment(YangNodeIdentifier nodeId, boolean isPrefix) {
        getAugmentJavaFileNameList().add(createName(nodeId, isPrefix));
        setAugmentJavaFileNameList(getAugmentJavaFileNameList());
        return getAugmentJavaFileNameList().get(getAugmentJavaFileNameList().size() - 1);
    }

    /**
     * Creates name for the current augment file.
     *
     * @param nodeId node identifier
     * @param isPrefix if prefix is present or it is not equals to parent's prefix
     */
    private static String createName(YangNodeIdentifier nodeId, boolean isPrefix) {
        if (isPrefix) {
            return AUGMENTED + getCapitalCase(nodeId.getPrefix()) + getCapitalCase(nodeId.getName());
        } else {
            return AUGMENTED + getCapitalCase(nodeId.getName());
        }
    }

    /**
     * Updates occurrence count of augment.
     */
    private static void updateOccurenceCount() {
        int count = getOccurrenceCount();
        count++;
        setOccurrenceCount(count);
    }

    /**
     * Updates the list of name when augment has occurred multiple times to update the same target node
     * and returns a valid name for augment node's generated java file.
     *
     * @param nodeId YANG node identifier
     * @param isPrefix true if a prefix is present and it is not equals to parents prefix
     * @return valid name for augment node
     */
    public static String updateNameWhenHasMultipleOuccrrence(YangNodeIdentifier nodeId, boolean isPrefix) {
        String name = "";
        updateOccurenceCount();

        if (getOccurrenceCount() == TWO) {
            String previousAugmentsName = getAugmentJavaFileNameList().get(getAugmentJavaFileNameList().size() - ONE);
            getAugmentJavaFileNameList().remove(ZERO);
            getAugmentJavaFileNameList().add(previousAugmentsName + ONE);
            //TODO: update when already contains the name.
            name = createName(nodeId, isPrefix) + TWO;
        } else {
            name = createName(nodeId, isPrefix) + getOccurrenceCount();
        }
        getAugmentJavaFileNameList().add(name);
        return name;
    }

    /**
     * Resets occurrence count to one.
     */
    public static void clearOccurrenceCount() {
        setOccurrenceCount(ONE);
    }

    /**
     * Returns true if a prefix is present and it is not equals to parents prefix.
     *
     * @param nodeId YANG node identifier
     * @param parentsPrefix parent's prefix
     * @return true if a prefix is present and it is not equals to parents prefix
     */
    private static boolean isPrefixPresent(YangNodeIdentifier nodeId, String parentsPrefix) {
        return nodeId.getPrefix() != null && nodeId.getPrefix() != parentsPrefix;
    }

    /**
     * Validates whether current node in target path is valid or not.
     *
     * @param curNode current YANG node
     * @param targetNodes list of target nodes
     * @param ctx augment statement context
     */
    public static void validateNodeInTargetPath(YangNode curNode, List<YangNodeIdentifier> targetNodes,
            GeneratedYangParser.AugmentStatementContext ctx) {

        curNode = curNode.getChild();
        YangNode tempNode = validateCurrentTargetNode(targetNodes, curNode);
        if (tempNode != null) {
            switch (tempNode.getNodeType()) {
                case CONTAINER_NODE:
                    break;
                case LIST_NODE:
                    break;
                case CHOICE_NODE:
                    break;
                case CASE_NODE:
                    break;
                case INPUT_NODE:
                    break;
                case OUTPUT_NODE:
                    break;
                case NOTIFICATION_NODE:
                    break;
                default:
                    throw parserException(ctx);
            }
        } else {
            throw parserException(ctx);
        }
    }

    /**
     * Validates whether nodes in target node list are valid or not.
     *
     * @param targetNodeName current target node
     * @param curNode YANG node
     * @return true or false
     */
    private static YangNode validateCurrentTargetNode(List<YangNodeIdentifier> targetNodes, YangNode curNode) {
        YangNode tempNode = null;
        while (curNode != null) {
            tempNode = curNode;
            for (int i = 1; i < targetNodes.size(); i++) {
                if (curNode.getName().equals(targetNodes.get(i).getName())) {
                    if (curNode.getChild() != null && targetNodes.size() - 1 != i) {
                        curNode = curNode.getChild();
                    } else if (curNode.getChild() != null && targetNodes.size() - 1 == i) {
                        return curNode;
                    } else if (curNode.getChild() == null && targetNodes.size() - 1 == i) {
                        return curNode;
                    } else {
                        break;
                    }
                } else {
                    curNode = tempNode;
                    break;
                }
            }
            curNode = curNode.getNextSibling();
        }
        return null;
    }

    /**
     * Builds parser exception.
     *
     * @param ctx augment statement context
     * @return parser exception
     */
    public static ParserException parserException(GeneratedYangParser.AugmentStatementContext ctx) {
        int line = ctx.getStart().getLine();
        int charPositionInLine = ctx.getStart().getCharPositionInLine();
        ParserException exception = new ParserException("invalid target node path.");
        exception.setLine(line);
        exception.setCharPosition(charPositionInLine);
        return exception;
    }

    /**
     * Returns parent nodes prefix.
     *
     * @param curNode current YANG node
     * @return parent nodes prefix
     */
    public static String getParentsPrefix(YangNode curNode) {
        String curPrefix = null;
        if (curNode instanceof YangModule) {
            curPrefix = ((YangModule) curNode).getPrefix();
        } else if (curNode instanceof YangSubModule) {
            curPrefix = ((YangSubModule) curNode).getPrefix();
        }
        return curPrefix;
    }
}
