/*
 * Copyright 2017-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.drivers.microsemi.yang.impl;

import com.google.common.base.Charsets;
import com.google.common.io.ByteSource;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.netconf.DatastoreId;
import org.onosproject.netconf.NetconfException;
import org.onosproject.netconf.NetconfSession;
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.CcmIntervalEnum;
import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.lossmeasurements.lossmeasurement.MessagePeriodEnum;
import org.onosproject.yang.model.ModelConverter;
import org.onosproject.yang.model.ModelObjectData;
import org.onosproject.yang.model.ResourceData;
import org.onosproject.yang.model.ResourceId;
import org.onosproject.yang.model.SchemaContext;
import org.onosproject.yang.model.SchemaContextProvider;
import org.onosproject.yang.runtime.AnnotatedNodeInfo;
import org.onosproject.yang.runtime.CompositeData;
import org.onosproject.yang.runtime.CompositeStream;
import org.onosproject.yang.runtime.DefaultCompositeData;
import org.onosproject.yang.runtime.DefaultCompositeStream;
import org.onosproject.yang.runtime.DefaultYangSerializerContext;
import org.onosproject.yang.runtime.YangModelRegistry;
import org.onosproject.yang.runtime.YangSerializer;
import org.onosproject.yang.runtime.YangSerializerContext;
import org.onosproject.yang.runtime.YangSerializerRegistry;
import org.onosproject.yang.serializers.xml.XmlSerializer;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * Abstract class that implements some of the core functions of a YANG model service.
 *
 */
@Component(immediate = true, service = AbstractYangServiceImpl.class)
public abstract class AbstractYangServiceImpl {
    public static final String NC_OPERATION = "nc:operation";
    public static final String OP_DELETE = "delete";

    protected final Logger log = LoggerFactory.getLogger(getClass());
    protected boolean alreadyLoaded = false;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected CoreService coreService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected YangModelRegistry yangModelRegistry;

    protected ApplicationId appId;

    // xSer is not a service and is a class variable. Can be lost on deactivate.
    // Must be recreated on activate
    protected XmlSerializer xSer = null;
    protected YangSerializerContext yCtx = null;

    protected static final Pattern REGEX_XML_HEADER =
            Pattern.compile("(<\\?xml).*(\\?>)", Pattern.DOTALL);
    protected static final Pattern REGEX_RPC_REPLY =
            Pattern.compile("(<rpc-reply)[ ]*" +
                    "(xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\")[ ]*" +
                    "(message-id=\")[0-9]*(\">)", Pattern.DOTALL);
    protected static final Pattern REGEX_RPC_REPLY_DATA_NS =
            Pattern.compile("(<data)[ ]*(xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)");
    protected static final Pattern REGEX_RPC_REPLY_DATA =
            Pattern.compile("(<data>)");
    protected static final Pattern REGEX_RPC_REPLY_DATA_CLOSE =
            Pattern.compile("(</data>)");
    protected static final Pattern REGEX_RPC_REPLY_DATA_EMPTY =
            Pattern.compile("(<data/>)");
    protected static final Pattern REGEX_RPC_REPLY_CLOSE =
            Pattern.compile("(</rpc-reply>)");
    protected static final Pattern REGEX_RPC_OK =
            Pattern.compile("\\R?\\s*(<ok/>)\\R?");
    @Activate
    public void activate() {
        Set<YangSerializer> yangSer = ((YangSerializerRegistry) yangModelRegistry).getSerializers();
        xSer = (XmlSerializer) yangSer.stream()
                .filter(ser -> (ser instanceof XmlSerializer)).findFirst().get();
        SchemaContext context = ((SchemaContextProvider) yangModelRegistry)
                .getSchemaContext(ResourceId.builder().addBranchPointSchema("/", null).build());

        yCtx = new DefaultYangSerializerContext(context, null);
    };

    @Deactivate
    public void deactivate() {
        alreadyLoaded = false;
    }

    /**
     * Internal method to generically make a NETCONF get query from YANG objects.
     * @param moFilter A YANG object model
     * @param session A NETCONF session
     * @return YangObjectModel
     * @throws NetconfException if the session has any error
     */
    protected final ModelObjectData getNetconfObject(
            ModelObjectData moFilter, NetconfSession session)
                throws NetconfException {

        return getConfigNetconfObject(moFilter, session, null);
    }

    /**
     * Internal method to generically make a NETCONF get-config query from YANG objects.
     *
     * @param moFilter A YANG object model
     * @param session A NETCONF session
     * @param targetDs - running,candidate or startup
     * @return YangObjectModel
     * @throws NetconfException if the session has any error
     */
    protected final ModelObjectData getConfigNetconfObject(
            ModelObjectData moFilter, NetconfSession session, DatastoreId targetDs)
                throws NetconfException {
        if (session == null) {
            throw new NetconfException("Session is null when calling getConfigNetconfObject()");
        }

        if (moFilter == null) {
            throw new NetconfException("Query object cannot be null");
        }

        String xmlQueryStr = encodeMoToXmlStr(moFilter, null);

        log.debug("Sending <get-(config)> query on NETCONF session " + session.getSessionId() +
                ":\n" + xmlQueryStr);
        String xmlResult;
        if (targetDs == null) {
            xmlResult = session.get(xmlQueryStr, null);
        } else {
            xmlResult = session.getConfig(targetDs, xmlQueryStr);
        }
        xmlResult = removeRpcReplyData(xmlResult);

        DefaultCompositeStream resultDcs = new DefaultCompositeStream(
                null, new ByteArrayInputStream(xmlResult.getBytes()));
        CompositeData compositeData = xSer.decode(resultDcs, yCtx);

        return ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
    }

    /**
     * Internal method to generically make a NETCONF edit-config call from a set of YANG objects.
     *
     * @param moConfig A YANG object model
     * @param session A NETCONF session
     * @param targetDs - running,candidate or startup
     * @param annotations A list of AnnotatedNodeInfos to be added to the DataNodes
     * @return Boolean value indicating success or failure of command
     * @throws NetconfException if the session has any error
     */
    protected final boolean setNetconfObject(
            ModelObjectData moConfig, NetconfSession session, DatastoreId targetDs,
            List<AnnotatedNodeInfo> annotations) throws NetconfException {
        if (moConfig == null) {
            throw new NetconfException("Query object cannot be null");
        } else if (session == null) {
            throw new NetconfException("Session is null when calling setNetconfObject()");
        } else if (targetDs == null) {
            throw new NetconfException("TargetDs is null when calling setNetconfObject()");
        }

        String xmlQueryStr = encodeMoToXmlStr(moConfig, annotations);
        log.debug("Sending <edit-config> query on NETCONF session " + session.getSessionId() +
                ":\n" + xmlQueryStr);

        //Some encoded values just have to be replaced
        xmlQueryStr = xmlQueryStr.replace(MessagePeriodEnum.YANGAUTOPREFIX3MS.toString(), "3ms");
        xmlQueryStr = xmlQueryStr.replace(MessagePeriodEnum.YANGAUTOPREFIX10MS.toString(), "10ms");
        xmlQueryStr = xmlQueryStr.replace(MessagePeriodEnum.YANGAUTOPREFIX100MS.toString(), "100ms");
        xmlQueryStr = xmlQueryStr.replace(MessagePeriodEnum.YANGAUTOPREFIX1000MS.toString(), "1000ms");

        xmlQueryStr = xmlQueryStr.replace(CcmIntervalEnum.YANGAUTOPREFIX3_3MS.toString(), "3.3ms");
        xmlQueryStr = xmlQueryStr.replace(CcmIntervalEnum.YANGAUTOPREFIX10MS.toString(), "10ms");
        xmlQueryStr = xmlQueryStr.replace(CcmIntervalEnum.YANGAUTOPREFIX100MS.toString(), "100ms");
        xmlQueryStr = xmlQueryStr.replace(CcmIntervalEnum.YANGAUTOPREFIX1S.toString(), "1s");

        return session.editConfig(targetDs, null, xmlQueryStr);
    }

    /**
     * Internal method to generically call a NETCONF custom RPC from a set of YANG objects.
     *
     * @param customRpcInput A YANG object model
     * @param rpcName The name of the RPC - replaces 'input' in the XML payload
     * @param session A NETCONF session
     * @return ModelObjectData value indicating success or failure of command
     * @throws NetconfException if the session has any error
     */
    protected final ModelObjectData customRpcNetconf(
            ModelObjectData customRpcInput, String rpcName, NetconfSession session)
            throws NetconfException {
        if (customRpcInput == null) {
            throw new NetconfException("Input object cannot be null");
        } else if (session == null) {
            throw new NetconfException("Session is null when calling customRpcNetconf()");
        }

        String xmlQueryStr = encodeMoToXmlStr(customRpcInput, null);
        xmlQueryStr = xmlQueryStr.replace("input", rpcName);
        log.debug("Sending <edit-config> query on NETCONF session " + session.getSessionId() +
                ":\n" + xmlQueryStr);

        String xmlResult = session.doWrappedRpc(xmlQueryStr);
        xmlResult = removeRpcReplyData(xmlResult);
        if (REGEX_RPC_OK.matcher(xmlResult).matches()) {
            return null;
        }

        DefaultCompositeStream resultDcs = new DefaultCompositeStream(
                null, new ByteArrayInputStream(xmlResult.getBytes()));
        CompositeData compositeData = xSer.decode(resultDcs, yCtx);

        return ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData());
    }

    protected final String encodeMoToXmlStr(ModelObjectData yangObjectOpParamFilter,
                                            List<AnnotatedNodeInfo> annotations)
            throws NetconfException {
        //Convert the param to XML to use as a filter
        ResourceData rd = ((ModelConverter) yangModelRegistry).createDataNode(yangObjectOpParamFilter);

        DefaultCompositeData.Builder cdBuilder =
                        DefaultCompositeData.builder().resourceData(rd);
        if (annotations != null) {
            for (AnnotatedNodeInfo ani : annotations) {
                cdBuilder.addAnnotatedNodeInfo(ani);
            }
        }
        CompositeStream cs = xSer.encode(cdBuilder.build(), yCtx);
        //Convert the param to XML to use as a filter

        try {
            ByteSource byteSource = new ByteSource() {
                @Override
                public InputStream openStream() throws IOException {
                    return cs.resourceData();
                }
            };

            return byteSource.asCharSource(Charsets.UTF_8).read();
        } catch (IOException e) {
            throw new NetconfException("Error decoding CompositeStream to String", e);
        }
    }

    protected static final String removeRpcReplyData(String rpcReplyXml) throws NetconfException {
        rpcReplyXml = REGEX_XML_HEADER.matcher(rpcReplyXml).replaceFirst("");
        if (rpcReplyXml.contains("<rpc-error")) {
            throw new NetconfException("NETCONF rpc-error: " + rpcReplyXml);
        }

        rpcReplyXml = REGEX_RPC_REPLY.matcher(rpcReplyXml).replaceFirst("");
        rpcReplyXml = REGEX_RPC_REPLY_DATA_NS.matcher(rpcReplyXml).replaceFirst("");
        rpcReplyXml = REGEX_RPC_REPLY_DATA.matcher(rpcReplyXml).replaceFirst("");
        rpcReplyXml = REGEX_RPC_REPLY_DATA_CLOSE.matcher(rpcReplyXml).replaceFirst("");
        rpcReplyXml = REGEX_RPC_REPLY_DATA_EMPTY.matcher(rpcReplyXml).replaceFirst("");
        rpcReplyXml = REGEX_RPC_REPLY_CLOSE.matcher(rpcReplyXml).replaceFirst("");
        rpcReplyXml = rpcReplyXml.replace("\t", "");
        return rpcReplyXml;
    }
}
