/*
 * 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.ych;

import org.onosproject.yangutils.datamodel.YangSchemaNode;
import org.onosproject.yangutils.datamodel.YangSchemaNodeContextInfo;
import org.onosproject.yangutils.datamodel.YangSchemaNodeIdentifier;
import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
import org.onosproject.yms.app.ych.defaultcodecs.YangCodecRegistry;
import org.onosproject.yms.app.ydt.YdtExtendedBuilder;
import org.onosproject.yms.app.ydt.YdtExtendedContext;
import org.onosproject.yms.app.yob.DefaultYobBuilder;
import org.onosproject.yms.app.ysr.YangSchemaRegistry;
import org.onosproject.yms.app.ytb.DefaultYangTreeBuilder;
import org.onosproject.yms.app.ytb.YtbException;
import org.onosproject.yms.ych.YangCodecHandler;
import org.onosproject.yms.ych.YangCompositeEncoding;
import org.onosproject.yms.ych.YangDataTreeCodec;
import org.onosproject.yms.ych.YangProtocolEncodingFormat;
import org.onosproject.yms.ydt.YdtBuilder;
import org.onosproject.yms.ydt.YdtContext;
import org.onosproject.yms.ydt.YmsOperationType;
import org.onosproject.yms.ysr.YangModuleLibrary;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.onosproject.yms.app.yob.YobUtils.createAndSetInEventInstance;
import static org.onosproject.yms.app.yob.YobUtils.createAndSetInEventSubjectInstance;

/**
 * Represents implementation of YANG SBI broker interfaces.
 * YCH acts as a broker between YMS and driver/provider.
 */
public class DefaultYangCodecHandler implements YangCodecHandler {

    private static final String E_MODULE_LIST = "The input module or " +
            "sub-module object list cannot be null.";
    private static final String E_DATA_TREE_CODEC = "data tree codec handler" +
            " is null.";
    private static final String E_DATA_MODEL_CHILD = "Unable to find the " +
            "child node";
    private static final String E_NOTIFICATION_NODE = "Notification node " +
            "should be the first child of module in YDT";

    /**
     * Schema registry for driver.
     */
    private final YangSchemaRegistry schemaRegistry;
    private YangModuleLibrary library;

    /**
     * Default codecs.
     */
    private final Map<YangProtocolEncodingFormat, YangDataTreeCodec>
            defaultCodecs = new HashMap<>();

    /**
     * Override codec handler.
     */
    private final Map<YangProtocolEncodingFormat, YangDataTreeCodec>
            overrideCodecs = new HashMap<>();

    /**
     * Creates a new YANG codec handler.
     *
     * @param registry YANG schema registry
     */
    public DefaultYangCodecHandler(YangSchemaRegistry registry) {
        schemaRegistry = registry;

        // update the default codecs from codec registry
        Map<YangProtocolEncodingFormat, YangDataTreeCodec> recvCodec =
                YangCodecRegistry.getDefaultCodecs();
        if (!recvCodec.isEmpty()) {
            for (Map.Entry<YangProtocolEncodingFormat, YangDataTreeCodec>
                    codecEntry : recvCodec.entrySet()) {
                defaultCodecs.put(codecEntry.getKey(), codecEntry.getValue());
            }
        }
    }

    private YangDataTreeCodec getAppropriateCodec(
            YangProtocolEncodingFormat dataFormat) {
        YangDataTreeCodec codec = defaultCodecs.get(dataFormat);

        int size = overrideCodecs.size();
        // Check over ridden codec handler is exist or not.
        if (size != 0) {
            YangDataTreeCodec overrideCodec = overrideCodecs.get(dataFormat);
            if (overrideCodec != null) {
                codec = overrideCodec;
            }
        }
        return codec;
    }

    @Override
    public void addDeviceSchema(Class<?> yangModule) {
        schemaRegistry.registerApplication(null, yangModule);
        schemaRegistry.processModuleLibrary(yangModule.getName(), library);
    }

    @Override
    public String encodeOperation(String rootName,
                                  String rootNamespace,
                                  Map<String, String> tagAttrMap,
                                  List<Object> moduleList,
                                  YangProtocolEncodingFormat dataFormat,
                                  YmsOperationType opType) {

        if (moduleList == null || moduleList.isEmpty()) {
            throw new YchException(E_MODULE_LIST);
        }

        // Get the default codec handler.
        YangDataTreeCodec codec = getAppropriateCodec(dataFormat);
        if (codec == null) {
            throw new YchException(E_DATA_TREE_CODEC);
        }

        // Get yang data tree from YTB for the received objects.
        DefaultYangTreeBuilder builder = new DefaultYangTreeBuilder();
        YdtExtendedBuilder encodedYdt =
                builder.getYdtBuilderForYo(moduleList, rootName,
                                           rootNamespace, opType,
                                           schemaRegistry);

        encodedYdt.setRootTagAttributeMap(tagAttrMap);

        // Get the xml string form codec handler.
        return codec.encodeYdtToProtocolFormat(encodedYdt);
    }

    @Override
    public YangCompositeEncoding encodeCompositeOperation(
            String rootName,
            String rootNamespace,
            Object moduleObject,
            YangProtocolEncodingFormat dataFormat,
            YmsOperationType opType) {

        if (moduleObject == null) {
            throw new YtbException(E_MODULE_LIST);
        }

        // Get the default codec handler.
        YangDataTreeCodec codec = getAppropriateCodec(dataFormat);
        if (codec == null) {
            throw new YchException(E_DATA_TREE_CODEC);
        }

        List<Object> yangModuleList = new ArrayList<>();
        yangModuleList.add(moduleObject);

        // Get yang data tree from YTB for the received objects.
        DefaultYangTreeBuilder builder = new DefaultYangTreeBuilder();
        YdtExtendedBuilder extBuilder =
                builder.getYdtBuilderForYo(yangModuleList,
                                           rootName,
                                           rootNamespace,
                                           opType,
                                           schemaRegistry);

        // Get the composite response from codec handler.
        return codec.encodeYdtToCompositeProtocolFormat(extBuilder);
    }

    @Override
    public List<Object> decode(String inputString,
                               YangProtocolEncodingFormat dataFormat,
                               YmsOperationType opType) {

        YdtBuilder ydtBuilder;
        YangDataTreeCodec codec = getAppropriateCodec(dataFormat);
        if (codec == null) {
            throw new YchException(E_DATA_TREE_CODEC);
        }

        try {
            // Get the YANG data tree
            ydtBuilder = codec.decodeProtocolDataToYdt(inputString,
                                                       schemaRegistry,
                                                       opType);
        } catch (Exception e) {
            throw new YchException(e.getLocalizedMessage());
        }

        if (ydtBuilder != null) {
            return getObjectList(ydtBuilder.getRootNode());
        }
        return null;
    }

    @Override
    public Object decode(YangCompositeEncoding protoData,
                         YangProtocolEncodingFormat dataFormat,
                         YmsOperationType opType) {

        YangDataTreeCodec codec = getAppropriateCodec(dataFormat);
        if (codec == null) {
            throw new YchException(E_DATA_TREE_CODEC);
        }

        YdtBuilder ydtBuilder =
                codec.decodeCompositeProtocolDataToYdt(protoData,
                                                       schemaRegistry,
                                                       opType);

        if (ydtBuilder == null) {
                return null;
        }

        YdtExtendedContext rootNode = ((YdtExtendedContext) ydtBuilder
                .getRootNode());

        if (opType == YmsOperationType.NOTIFICATION) {
            return getNotificationObject(((YdtExtendedContext) rootNode
                    .getFirstChild()));
        }

        // Return the module object by using YANG data tree
        return getObjectList(rootNode);
    }

    //returns notification event object
    private Object getNotificationObject(YdtExtendedContext rootNode) {
        YangSchemaNode module = rootNode.getYangSchemaNode();
        YangSchemaNode childSchema = ((YdtExtendedContext) rootNode
                .getFirstChild()).getYangSchemaNode();

        YangSchemaNodeIdentifier id = new YangSchemaNodeIdentifier();
        id.setNameSpace(childSchema.getNameSpace());
        id.setName(childSchema.getName());

        YangSchemaNodeContextInfo contextInfo;
        try {
            contextInfo = module.getChildSchema(id);
        } catch (DataModelException e) {
            throw new YchException(E_DATA_MODEL_CHILD);
        }

        if (contextInfo == null) {
            throw new YchException(E_NOTIFICATION_NODE);
        }

        DefaultYobBuilder builder = new DefaultYobBuilder();
        Object object = builder.getYangObject(((YdtExtendedContext) rootNode
                                                      .getFirstChild()),
                                              schemaRegistry);

        Object eventSubObj = createAndSetInEventSubjectInstance(object,
                                                                rootNode,
                                                                schemaRegistry);
        return createAndSetInEventInstance(eventSubObj, rootNode,
                                           schemaRegistry);
    }

    @Override
    public void registerOverriddenCodec(YangDataTreeCodec overrideCodec,
                                        YangProtocolEncodingFormat dataFormat) {
        overrideCodecs.put(dataFormat, overrideCodec);
    }

    /**
     * Returns the list of objects from YDT data tree.
     *
     * @param rootNode YDT root node
     * @return returns list of objects
     */
    private List<Object> getObjectList(YdtContext rootNode) {

        if (rootNode == null) {
            // TODO
            return null;
        }

        if (rootNode.getFirstChild() == null) {
            // TODO
            return null;
        }

        YdtContext curNode = rootNode.getFirstChild();
        DefaultYobBuilder builder = new DefaultYobBuilder();
        Object object = builder.getYangObject((YdtExtendedContext) curNode,
                                              schemaRegistry);
        List<Object> objectList = new ArrayList<>();
        objectList.add(object);

        // Check next module is exit or not. If exist get the object for that.
        while (curNode.getNextSibling() != null) {
            curNode = curNode.getNextSibling();
            object = builder.getYangObject((YdtExtendedContext) curNode,
                                           schemaRegistry);
            objectList.add(object);
        }

        return objectList;
    }

    /**
     * Returns module library for YSR.
     *
     * @return module library for YSR
     */
    public YangModuleLibrary getLibrary() {
        return library;
    }

    /**
     * Sets module library for YSR.
     *
     * @param library module library for YSR
     */
    public void setLibrary(YangModuleLibrary library) {
        this.library = library;
    }
}
