/*
 * Copyright 2016-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.yms.app.ydt;

import com.google.common.collect.ImmutableMap;
import org.onosproject.yangutils.datamodel.YangAugment;
import org.onosproject.yangutils.datamodel.YangLeaf;
import org.onosproject.yangutils.datamodel.YangList;
import org.onosproject.yangutils.datamodel.YangSchemaNode;
import org.onosproject.yangutils.datamodel.YangSchemaNodeContextInfo;
import org.onosproject.yangutils.datamodel.YangSchemaNodeIdentifier;
import org.onosproject.yms.app.ydt.exceptions.YdtException;
import org.onosproject.yms.app.ysr.YangSchemaRegistry;
import org.onosproject.yms.ydt.YdtContext;
import org.onosproject.yms.ydt.YdtContextOperationType;
import org.onosproject.yms.ydt.YdtType;
import org.onosproject.yms.ydt.YmsOperationType;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.onosproject.yms.app.ydt.AppNodeFactory.getAppContext;
import static org.onosproject.yms.app.ydt.RequestedCallType.LEAF;
import static org.onosproject.yms.app.ydt.RequestedCallType.NON_LEAF;
import static org.onosproject.yms.app.ydt.RequestedCardinality.MULTI_INSTANCE;
import static org.onosproject.yms.app.ydt.RequestedCardinality.MULTI_INSTANCE_LEAF;
import static org.onosproject.yms.app.ydt.RequestedCardinality.SINGLE_INSTANCE;
import static org.onosproject.yms.app.ydt.RequestedCardinality.UNKNOWN;
import static org.onosproject.yms.app.ydt.YdtConstants.errorMsg;
import static org.onosproject.yms.app.ydt.YdtNodeFactory.getNode;
import static org.onosproject.yms.app.ydt.YdtNodeFactory.getYangSchemaNodeTypeSpecificContext;
import static org.onosproject.yms.app.ydt.YdtUtils.checkElementCount;
import static org.onosproject.yms.app.ydt.YdtUtils.freeRestResources;
import static org.onosproject.yms.app.ydt.YdtUtils.getAppOpTypeFromYdtOpType;
import static org.onosproject.yms.app.ydt.YdtUtils.getAugmentingSchemaNode;
import static org.onosproject.yms.app.ydt.YdtUtils.getNodeIdentifier;
import static org.onosproject.yms.app.ydt.YdtUtils.getValidOpType;
import static org.onosproject.yms.ydt.YdtContextOperationType.DELETE;
import static org.onosproject.yms.ydt.YdtContextOperationType.REMOVE;
import static org.onosproject.yms.ydt.YdtType.MULTI_INSTANCE_LEAF_VALUE_NODE;
import static org.onosproject.yms.ydt.YdtType.MULTI_INSTANCE_NODE;

/**
 * Represents YANG request work bench which contains all parameters for
 * request handling and methods to build and obtain YANG data tree
 * which is data (sub)instance representation, abstract of protocol.
 */
public class YangRequestWorkBench implements YdtExtendedBuilder {

    // Ydt formatted error string
    private static final String FMT_NOT_EXIST =
            "Application with name \"%s\" doesn't exist.";

    // Ydt error strings.
    private static final String E_USE_ADD_LEAF =
            "Requested Node should be created using addLeaf interface.";

    private static final String E_INVOKE_PARENT =
            "Can't invoke get parent at logical root node.";

    /*
     * Reference for the current context node in YANG data tree.
     */
    private YdtNode curNode;

    /*
     * Reference for the logical root node in YANG data tree.
     */
    private YdtNode rootNode;

    /*
     * Reference for the current context in ydt application tree.
     */
    private YdtAppContext appCurNode;

    /*
     * Reference for the logical root node context in ydt application tree.
     */
    private YdtAppContext appRootNode;

    /**
     * Root Node Tag attribute in YANG data tree, kept to maintain the root
     * tag attributes in YDT.
     * <p>
     * First key param of map represent tagName  name of tag attribute.
     * Second param of map represent tagValue value of tag attribute
     */
    private Map<String, String> rootTagAttributeMap;

    /*
     * YANG schema registry reference.
     */
    private YangSchemaRegistry registry = null;

    /*
     * YMS operation type.
     */
    private final YmsOperationType ymsOperationType;

    /*
     * YDT default operation type.
     */
    private YdtContextOperationType ydtDefaultOpType;

    /*
     * Flag to identify data validation need to be done by YDT or not.
     */
    private boolean validate = false;
    // TODO validate need to be handle later with interaction type basis in
    // future when it will be supported

    /*
     * Reference for application tree node set.
     * This set contains the method name's generated for an augmented
     * target node to avoid the duplicate entries in YDT application tree for
     * multiple augmented nodes under a single XPATH.
     */
    private Set<String> augGenMethodSet;

    /**
     * Creates an instance of YANG request work bench which is use to initialize
     * logical rootNode and and schema registry.
     *
     * @param name       name of logical container of a protocol
     *                   which is a holder of the complete tree
     * @param namespace  namespace of logical container
     * @param opType     type of operation done by using YANG
     *                   interface
     * @param reg        Yang schema registry
     * @param isValidate Flag to identify data validation need to be
     *                   done by YDT or not
     */
    public YangRequestWorkBench(String name, String namespace,
                                YmsOperationType opType,
                                YangSchemaRegistry reg,
                                boolean isValidate) {

        setRootNode(new YdtLogicalNode(name, namespace));
        registry = reg;
        ymsOperationType = opType;
        validate = isValidate;

        setAppRootNode(getAppContext(true));
    }

    /**
     * Sets the logical root node for ydt.
     *
     * @param node ydt logical root node
     */
    private void setRootNode(YdtNode node) {
        rootNode = node;
        curNode = node;
    }

    /**
     * Sets the logical root node for ydt application tree.
     *
     * @param node ydt application context logical root node
     */
    private void setAppRootNode(YdtAppContext node) {
        appRootNode = node;
        appCurNode = node;
    }

    /**
     * Returns the YANG schema registry of Ydt.
     * This method will be used by ytb.
     *
     * @return YANG schema registry
     */
    public YangSchemaRegistry getYangSchemaRegistry() {
        return registry;
    }

    /**
     * Returns the ydt app context tree logical root node.
     * This method will be used by yab and ytb.
     *
     * @return YdtAppContext app tree logical root node
     */
    public YdtAppContext getAppRootNode() {
        return appRootNode;
    }

    /**
     * Returns the ydt module node with requested node identifier.
     *
     * @param id module/application node identifier
     * @return YANG data tree node
     * @throws YdtException when user requested node schema doesn't exist or
     *                      requested node is already part of the tree
     */
    private YdtNode moduleHandler(YangSchemaNodeIdentifier id)
            throws YdtException {

        YangSchemaNode node =
                registry.getYangSchemaNodeUsingSchemaName(id.getName());

        String namespace = id.getNameSpace().getModuleNamespace();

        /*
         * Checking received schema node is having same namespace as
         * requested by user or not.
         */
        if (node == null || namespace != null &&
                !namespace.equals(node.getYangSchemaNodeIdentifier()
                                          .getNameSpace()
                                          .getModuleNamespace())) {
            throw new YdtException(errorMsg(FMT_NOT_EXIST, id.getName()));
        }

        /*
         * If yms operation is for query then no validation need to be
         * performed.
         */
        if (ymsOperationType != YmsOperationType.QUERY_REQUEST) {
            // Checking whether module node is already exits in YDT or not.
            try {
                curNode.getCollidingChild(id);
            } catch (YdtException e) {
                throw new YdtException(e.getLocalizedMessage());
            }
        }

        YdtNode newNode = new YdtSingleInstanceNode(node);
        newNode.setYangSchemaNode(node);
        return newNode;
    }

    @Override
    public void setRootTagAttributeMap(Map<String, String> attributeTag) {
        rootTagAttributeMap = attributeTag;
    }

    @Override
    public Map<String, String> getRootTagAttributeMap() {
        if (rootTagAttributeMap != null) {
            return ImmutableMap.copyOf(rootTagAttributeMap);
        }
        return null;
    }

    @Override
    public void addChild(String name, String namespace)
            throws IllegalArgumentException {
        addChild(name, namespace, UNKNOWN, null, NON_LEAF);
    }

    @Override
    public void addChild(String name, String namespace, YdtType ydtType)
            throws IllegalArgumentException {
        addChild(name, namespace, ydtType, null);
    }

    @Override
    public void addChild(String name, String namespace,
                         YdtContextOperationType opType)
            throws IllegalArgumentException {
        addChild(name, namespace, UNKNOWN, opType, NON_LEAF);
    }

    @Override
    public void addChild(String name, String namespace, YdtType ydtType,
                         YdtContextOperationType opType)
            throws IllegalArgumentException {
        RequestedCardinality cardinality;
        switch (ydtType) {
            case MULTI_INSTANCE_NODE:
                cardinality = MULTI_INSTANCE;
                break;
            case SINGLE_INSTANCE_NODE:
                cardinality = SINGLE_INSTANCE;
                break;
            default:
                throw new IllegalArgumentException(E_USE_ADD_LEAF);
        }
        addChild(name, namespace, cardinality, opType, NON_LEAF);
    }

    /**
     * Adds a last child to YANG data tree; this method is to be used by all
     * protocols internally which are aware or unaware of the nature
     * (single/multiple) of node.
     *
     * @param name        name of child to be added
     * @param namespace   namespace of child to be added
     * @param cardinality type of YANG data tree node operation
     * @param opType      type of requested operation over a node
     * @param callType    to identify the whether its a leaf or other node
     * @throws IllegalArgumentException when method has been passed an illegal
     *                                  or inappropriate argument.
     */
    private void addChild(String name, String namespace,
                          RequestedCardinality cardinality,
                          YdtContextOperationType opType,
                          RequestedCallType callType)
            throws IllegalArgumentException {

        YdtNode newNode;
        boolean contextSwitch = false;
        YangSchemaNode augmentingSchema = null;
        YangSchemaNodeIdentifier id = getNodeIdentifier(name, namespace);
        if (name == null) {
            if (!curNode.equals(rootNode)) {
                throw new YdtException("Name is null for node other than module");
            }

            /*
             * Since XML will not have module name, id.name will be null. In
             * that case get schema node by using namespace. In NBI flow,
             * name will never be null.
             */
            YangSchemaNode node = registry
                    .getSchemaWrtNameSpace(id.getNameSpace().getModuleNamespace());
            id.setName(node.getName());
        }

        try {
            // Module/sub-module node handler.
            if (curNode.equals(rootNode)) {
                newNode = moduleHandler(id);
            } else {

                YangSchemaNode schemaNode;
                YangSchemaNodeContextInfo contextInfo;

                // If namespace given by user null, then take namespace from parent.
                if (namespace == null) {
                    id.setNameSpace(curNode.getYangSchemaNode().getNameSpace());
                }

                /*
                 * Get the already exiting YDT node in YDT tree with same
                 * nodeIdentifier
                 */
                newNode = curNode.getCollidingChild(id);

                /*
                 * If colliding child doesn't exist ,
                 * then query yang data model for schema of given node.
                 */
                if (newNode == null) {
                    /*
                     * Get Yang Schema node context info which is having
                     * YangSchemaNode and ContextSwitchedNode.
                     */
                    contextInfo = curNode.getSchemaNodeContextInfo(id);

                    if (contextInfo.getContextSwitchedNode() != null) {
                        augmentingSchema = getAugmentingSchemaNode(
                                id, contextInfo);
                        if (augmentingSchema != null) {
                            /*
                             * As two tree(YDT and YDT Application Tree) are getting
                             * prepared in parallel, So  setting context switch
                             * flag it will help ydt to keep the track whether
                             * ydtApp tree also need to be traversed back to parent
                             * or not with YDT tree traverse to parent call.
                             */
                            contextSwitch = true;
                        }
                    }
                    schemaNode = contextInfo.getSchemaNode();
                } else {
                    /*
                     * If colliding child exist , then it will be leaf-list or list.
                     * If its leaf-list then return and add new requested
                     * value/valueSet in same node else take yang data model
                     * information from colliding child.
                     */
                    if (newNode.getYdtType() == MULTI_INSTANCE_LEAF_VALUE_NODE) {
                        curNode = newNode;
                        return;
                    }
                    schemaNode = newNode.getYangSchemaNode();
                }

                /*
                 * For yms query request node specific validation are not
                 * required as rest-conf can call addChild api for leaf/leaf-list
                 * node addition also in ydt.
                 */
                if (ymsOperationType == YmsOperationType.QUERY_REQUEST) {
                    newNode = getYangSchemaNodeTypeSpecificContext(schemaNode);
                } else {
                    newNode = getNode(schemaNode, cardinality, callType);
                }
            }

            opType = getValidOpType(opType, ydtDefaultOpType, newNode, curNode);

            newNode.setYdtContextOperationType(opType);

            curNode.addChild(newNode, true);
        } catch (YdtException e) {
            freeRestResources(rootNode);
            throw new IllegalArgumentException(e.getLocalizedMessage());
        }

        // Update parent ydt node map.
        curNode.updateYdtMap(newNode);

        processAppTree(opType, newNode, augmentingSchema, contextSwitch);

        curNode = newNode;
    }

    /**
     * Processes application tree on the bases of requested ydt node.
     *
     * @param opType           user requested operation type
     * @param childNode        requested ydt node
     * @param augmentingSchema schema of last augmenting node
     * @param contextSwitch    true, for module node call; false for modules
     *                         sub-node calls
     */
    private void processAppTree(
            YdtContextOperationType opType, YdtNode childNode,
            YangSchemaNode augmentingSchema, boolean contextSwitch) {

        if (curNode == rootNode) {
            augGenMethodSet = new HashSet<>();
        }

        if (opType == null) {
            opType = curNode.getYdtContextOperationType();
        } else {
            // Updating operation type for parent nodes
            appCurNode.updateAppOperationType(opType);
        }

        /*
         * This is to avoid multiple entries of single augmented target.
         */
        if (augmentingSchema != null) {
            if (!augGenMethodSet.add(((YangAugment) augmentingSchema)
                                             .getSetterMethodName())) {
                return;
            }
        }

        /*
         * Create entry of module node in ydt app tree.
         * Or if context switch happened then also add entry for same
         * augmented ydt node in the ydt application tree.
         */
        if (curNode.equals(rootNode) || contextSwitch) {
            addChildInAppTree(childNode, augmentingSchema, opType,
                              contextSwitch);

            // Setting app tree node operation.
            appCurNode.setOperationType(getAppOpTypeFromYdtOpType(opType));
        }

        // Updating the delete operation list in app tree.
        if (opType == DELETE || opType == REMOVE) {
            appCurNode.addDeleteNode(childNode);
        }
    }


    /**
     * Adds a last child to YANG app data tree.this method is to be used
     * internally by other ydt interfaces.
     *
     * @param childNode       node to be added in tree
     * @param schemaNode      last augmenting module node
     * @param childOpType     operation type of node
     * @param isContextSwitch true, for module node call; false for modules
     *                        sub-node calls
     */
    private void addChildInAppTree(YdtNode childNode,
                                   YangSchemaNode schemaNode,
                                   YdtContextOperationType childOpType,
                                   boolean isContextSwitch) {

        YdtAppNodeOperationType opType;

        DefaultYdtAppContext appContext = getAppContext(isContextSwitch);

        // Add context switched child in ydt App tree.
        appCurNode.addChild(appContext);

        appCurNode = appContext;

        opType = getAppOpTypeFromYdtOpType(childOpType);

        appCurNode.setAppData(childNode, schemaNode);

        appCurNode.setOperationType(opType);

        childNode.setAppContextSwitch();
    }

    @Override
    public void addLeaf(String name, String namespace, String value)
            throws IllegalArgumentException {
        addLeaf(name, namespace, value, null, UNKNOWN);
    }

    @Override
    public void addLeaf(String name, String namespace, Set<String> valueSet)
            throws IllegalArgumentException {
        addLeaf(name, namespace, null, valueSet, MULTI_INSTANCE_LEAF);
    }

    @Override
    public void addNode(String name, String namespace)
            throws IllegalArgumentException {
        addChild(name, namespace, RequestedCardinality.UNKNOWN,
                null, RequestedCallType.EMPTY_CONTAINER);
    }


    /**
     * Adds a last leaf with list of values/single value to YANG data tree.
     * This method is used by all protocols which knows the nature
     * (single/multiple) or not.
     * Value of leaf can be null which indicates selection node in get
     * operation.
     *
     * @param name        name of child to be added
     * @param namespace   namespace of child to be added, if it's
     *                    null, parent's
     *                    namespace will be applied to child
     * @param value       value of the child
     * @param valueSet    list of value of the child
     * @param cardinality type of YANG data tree node operation
     * @throws IllegalArgumentException when method has been passed an illegal
     *                                  or inappropriate argument.
     */
    private void addLeaf(String name, String namespace, String value,
                         Set<String> valueSet,
                         RequestedCardinality cardinality)
            throws IllegalArgumentException {
        try {
            addChild(name, namespace, cardinality, null, LEAF);

            // After successful addition of child node updating the values in same.
            if (value != null) {
                curNode.addValue(value);
            } else if (valueSet != null) {
                curNode.addValueSet(valueSet);
            }
        } catch (YdtException e) {
            freeRestResources(rootNode);
            throw new IllegalArgumentException(e.getLocalizedMessage());
        }
    }

    @Override
    public void traverseToParent() throws IllegalStateException {
        // If traverse back to parent for logical root node comes
        if (curNode.equals(rootNode)) {
            freeRestResources(rootNode);
            throw new IllegalStateException(E_INVOKE_PARENT);
        }

        try {

            // If node is of multiInstanceNode type then check key uniqueness.
            if (curNode.getYdtType() == MULTI_INSTANCE_NODE) {
                List<YdtContext> keyList = ((YdtMultiInstanceNode) curNode).getKeyNodeList();
                if (keyList == null || keyList.isEmpty()) {
                    curNode.createKeyNodeList();
                }
            }

            /*
             * Check application switch for curNode if set,
             * then traverseToParent in YDT application tree.
             */
            if (curNode.getParent().equals(rootNode) ||
                    curNode.getAppContextSwitch()) {
                traverseToAppTreeParent();
            }

            /*
             * Validate all multi Instance inside current context,
             * This is not valid for leaf and leaf-list node.
             */
            if (curNode instanceof YdtMultiInstanceNode ||
                    curNode instanceof YdtSingleInstanceNode) {
                curNode.validateMultiInstanceNode();
            }

            curNode = curNode.getParent();
        } catch (YdtException e) {
            freeRestResources(rootNode);
            throw new IllegalStateException(e.getLocalizedMessage());
        }
    }

    /**
     * Traverses up in YANG application tree to the parent node,
     * This will be used when Ydt current context switch flag is set.
     */
    private void traverseToAppTreeParent() {
        appCurNode = appCurNode.getParent();
    }

    @Override
    public YdtExtendedContext getCurNode() {
        return curNode;
    }

    @Override
    public void setDefaultEditOperationType(
            YdtContextOperationType opType) {
        ydtDefaultOpType = opType;
    }

    @Override
    public YdtExtendedContext getRootNode() {
        return rootNode;
    }

    @Override
    public YmsOperationType getYmsOperationType() {
        return ymsOperationType;
    }

    @Override
    public void addMultiInstanceChild(String name, String namespace,
                                      List<String> keysValueList,
                                      YdtContextOperationType opType)
            throws IllegalArgumentException {

        addChild(name, namespace, UNKNOWN, opType,
                 RequestedCallType.MULTI_INSTANCE);
        int inputCount = keysValueList.size();

        try {
            if (curNode.getYdtType() == MULTI_INSTANCE_LEAF_VALUE_NODE) {

            /*
             * Calculating the current leaf-list node array size by adding
             * existing elements count and new supplied elements by user for
             * the same.
             */
                // TODO instance count for leaf list need to be handled.
//            if (curNode.getValueSet().size() + inputCount > expectedCount) {
//                curNode.errorHandler(
//                        errorMsg(FMT_MANY_INS, name, expectedCount), rootNode);
//            }

            /*
             * After successful addition of child node updating
             * the values in same.
             */
                for (String value : keysValueList) {
                    curNode.addValue(value);
                }
            } else if (curNode.getYdtType() == MULTI_INSTANCE_NODE) {

                YangList yangListHolder = (YangList) curNode.getYangSchemaNode();
                List<String> schemaKeyList = yangListHolder.getKeyList();
                int expectedCount = schemaKeyList.size();
                checkElementCount(name, expectedCount, inputCount);

                //After validation adding the key nodes under the list node.
                Iterator<String> sklIter = schemaKeyList.iterator();
                Iterator<String> kvlIter = keysValueList.iterator();
                String keyEleName;

                while (kvlIter.hasNext()) {
                    String value = kvlIter.next();
                    keyEleName = sklIter.next();
                    addLeaf(keyEleName, namespace, value);
                    if (kvlIter.hasNext()) {
                        traverseToParentWithoutValidation();
                    }
                }

                curNode = curNode.getParent();
                curNode.createKeyNodeList();
            }
        } catch (YdtException e) {
            freeRestResources(rootNode);
            throw new IllegalArgumentException(e.getLocalizedMessage());
        }
    }

    /**
     * Adds a last child to YANG data tree, this method is to be used by
     * YANG object builder sub-calls internally.
     *
     * @param opType type of requested operation over a node
     * @return returns added ydt node in YDT tree
     */
    private YdtNode addExtendedChildNode(YdtContextOperationType opType,
                                         YangSchemaNode schemaNode) {

        YdtNode childNode = getYangSchemaNodeTypeSpecificContext(schemaNode);

        childNode.setYangSchemaNode(schemaNode);

        childNode.setYdtContextOperationType(opType);

        curNode.addChild(childNode, true);

        curNode = childNode;

        return childNode;
    }

    @Override
    public YdtExtendedContext addChild(YdtContextOperationType opType,
                                       YangSchemaNode schemaNode) {
        return addExtendedChildNode(opType, schemaNode);
    }

    @Override
    public YdtExtendedContext addLeafList(Set<String> valueSet,
                                          YangSchemaNode schemaNode) {
        YdtNode childNode = addExtendedChildNode(null, schemaNode);

        /*
         * After successful addition of child node updating the values in
         * valueSet.
         */
        childNode.addValueSetWithoutValidation(valueSet);
        return childNode;
    }

    @Override
    public YdtExtendedContext addLeaf(String value, YangSchemaNode schemaNode) {

        YdtNode childNode = addExtendedChildNode(null, schemaNode);

        // After successful addition of child node updating the values in same.
        childNode.addValueWithoutValidation(value, ((YangLeaf) schemaNode)
                .isKeyLeaf());
        return childNode;
    }

    @Override
    public void traverseToParentWithoutValidation()
            throws IllegalStateException {
        // If traverse back to parent for logical root node comes.
        if (curNode.equals(rootNode)) {
            freeRestResources(rootNode);
            throw new IllegalStateException(E_INVOKE_PARENT);
        }
        curNode = curNode.getParent();
    }

    /**
     * Returns the method name's set for an augmented target node in an
     * application tree.
     *
     * @return augGenMethodSet set of method name's
     */
    public Set<String> getAugGenMethodSet() {
        return augGenMethodSet;
    }

    /**
     * Sets the method name's set for an augmented target node in an
     * application tree.
     *
     * @param augGenMethodSet set of method name's
     */
    public void setAugGenMethodSet(Set<String> augGenMethodSet) {
        this.augGenMethodSet = augGenMethodSet;
    }
}
