/*
 * 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.yms.app.ych.defaultcodecs.xml;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Namespace;
import org.onosproject.yms.app.ych.YchException;
import org.onosproject.yms.app.ych.defaultcodecs.netconf.NetconfCodec;
import org.onosproject.yms.app.ych.defaultcodecs.utils.DefaultCodecUtils;
import org.onosproject.yms.app.ydt.DefaultYdtWalker;
import org.onosproject.yms.app.ydt.YangRequestWorkBench;
import org.onosproject.yms.app.ydt.YdtExtendedBuilder;
import org.onosproject.yms.app.ydt.YdtExtendedContext;
import org.onosproject.yms.app.ydt.YdtExtendedWalker;
import org.onosproject.yms.app.ysr.YangSchemaRegistry;
import org.onosproject.yms.ych.YangCompositeEncoding;
import org.onosproject.yms.ych.YangDataTreeCodec;
import org.onosproject.yms.ydt.YdtBuilder;
import org.onosproject.yms.ydt.YmsOperationType;

import java.util.Map;

import static org.onosproject.yms.ych.YangProtocolEncodingFormat.XML;
import static org.onosproject.yms.ydt.YdtContextOperationType.CREATE;

/**
 * Represents an implementation of YCH data tree codec interface.
 */
public class DefaultXmlCodec implements YangDataTreeCodec {

    private static final String E_RESTCONF_ROOT = "/onos/restconf";
    private static final String E_YDT_ROOT_NODE = "YDT extended root node " +
            "is null.";
    private static final String E_ROOT_ELEMENT = "Root element in XML " +
            "input string is not well-formed.";
    private static final String E_ROOT_KEY_ELEMENT = "Root element " +
            "(filter, config, data) in XML input string is not found.";


    /**
     * Creates a new YANG xml codec.
     */
    public DefaultXmlCodec() {
    }

    /**
     * Returns the xml string from YDT.
     *
     * @param ydtBuilder YDT builder
     * @return the xml string from YDT
     */
    private String buildXmlForYdt(YdtBuilder ydtBuilder) {

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

        if (rootNode == null) {
            throw new YchException(E_YDT_ROOT_NODE);
        }

        // Creating the root element for xml.
        Element rootElement =
                DocumentHelper.createDocument().addElement(rootNode.getName());

        // Adding the name space if exist for root name.
        if (rootNode.getNamespace() != null) {
            rootElement.add(Namespace.get(rootNode.getNamespace()));
        }

        // Adding the attribute if exist
        Map<String, String> tagAttrMap = extBuilder.getRootTagAttributeMap();
        if (tagAttrMap != null && !tagAttrMap.isEmpty()) {
            for (Map.Entry<String, String> attr : tagAttrMap.entrySet()) {
                rootElement.addAttribute(attr.getKey(), attr.getValue());
            }
        }

        XmlCodecYdtListener listener = new XmlCodecYdtListener(XML, rootNode);
        listener.getElementStack().push(rootElement);

        // Walk through YDT and build the xml.
        YdtExtendedWalker extWalker = new DefaultYdtWalker();
        extWalker.walk(listener, rootNode);

        return rootElement.asXML();
    }

    @Override
    public String encodeYdtToProtocolFormat(YdtBuilder ydtBuilder) {
        return buildXmlForYdt(ydtBuilder);
    }

    @Override
    public YangCompositeEncoding encodeYdtToCompositeProtocolFormat(
            YdtBuilder ydtBuilder) {

        YangCompositeEncodingImpl encoding = new YangCompositeEncodingImpl();
        encoding.setResourceIdentifier(null);
        encoding.setResourceInformation(buildXmlForYdt(ydtBuilder));
        return encoding;
    }

    @Override
    public YdtBuilder decodeCompositeProtocolDataToYdt(
            YangCompositeEncoding protoData,
            Object schemaReg,
            YmsOperationType opType) {

        YdtExtendedBuilder extBuilder =
                new YangRequestWorkBench(E_RESTCONF_ROOT, null,
                                         opType,
                                         (YangSchemaRegistry) schemaReg,
                                         false);

        DefaultCodecUtils.convertUriToYdt(protoData.getResourceIdentifier(),
                                          extBuilder,
                                          CREATE);
        Document document;

        try {
            document = DocumentHelper
                    .parseText(protoData.getResourceInformation());
        } catch (DocumentException e) {
            throw new YchException(E_ROOT_ELEMENT);
        }

        XmlCodecListener listener = new XmlCodecListener();
        listener.setYdtExtBuilder(extBuilder);

        // Walk through xml and build the yang data tree.
        XmlWalker walker = new DefaultXmlCodecWalker();
        walker.walk(listener, document.getRootElement(),
                    document.getRootElement());
        return extBuilder;
    }

    @Override
    public YdtBuilder decodeProtocolDataToYdt(String protoData,
                                              Object schemaReg,
                                              YmsOperationType opType) {
        Document document;

        try {
            document = DocumentHelper.parseText(protoData);
        } catch (DocumentException e) {
            throw new YchException(E_ROOT_ELEMENT);
        }

        NetconfCodec codec = new NetconfCodec();
        // Find the root element in xml string
        Element rootElement =
                codec.getDataRootElement(document.getRootElement(), opType);

        if (rootElement == null) {
            throw new YchException(E_ROOT_KEY_ELEMENT);
        }

        // Get the YDT builder for the logical root name.
        YdtExtendedBuilder extBuilder =
                new YangRequestWorkBench(rootElement.getName(),
                                         rootElement.getNamespaceURI(),
                                         opType,
                                         (YangSchemaRegistry) schemaReg,
                                         false);

        XmlCodecListener listener = new XmlCodecListener();
        listener.setYdtExtBuilder(extBuilder);
        // Walk through xml and build the yang data tree.
        XmlWalker walker = new DefaultXmlCodecWalker();
        walker.walk(listener, rootElement, rootElement);
        return extBuilder;
    }
}
