/*
 * 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.d.config.sync.impl.netconf;

import static com.google.common.base.Preconditions.checkNotNull;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.concurrent.CompletableFuture.completedFuture;
import static org.slf4j.LoggerFactory.getLogger;

import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;

import org.onlab.util.XmlString;
import org.onosproject.d.config.ResourceIds;
import org.onosproject.d.config.sync.DeviceConfigSynchronizationProvider;
import org.onosproject.d.config.sync.impl.netconf.NetconfDeviceConfigSynchronizerComponent.NetconfContext;
import org.onosproject.d.config.sync.operation.SetRequest;
import org.onosproject.d.config.sync.operation.SetRequest.Change;
import org.onosproject.d.config.sync.operation.SetRequest.Change.Operation;
import org.onosproject.d.config.sync.operation.SetResponse;
import org.onosproject.d.config.sync.operation.SetResponse.Code;
import org.onosproject.net.DeviceId;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.netconf.NetconfDevice;
import org.onosproject.netconf.NetconfException;
import org.onosproject.netconf.NetconfSession;
import org.onosproject.yang.model.DataNode;
import org.onosproject.yang.model.DefaultResourceData;
import org.onosproject.yang.model.InnerNode;
import org.onosproject.yang.model.ResourceData;
import org.onosproject.yang.model.ResourceId;
import org.onosproject.yang.runtime.AnnotatedNodeInfo;
import org.onosproject.yang.runtime.Annotation;
import org.onosproject.yang.runtime.CompositeStream;
import org.onosproject.yang.runtime.DefaultAnnotatedNodeInfo;
import org.onosproject.yang.runtime.DefaultAnnotation;
import org.onosproject.yang.runtime.DefaultCompositeData;
import org.onosproject.yang.runtime.DefaultRuntimeContext;
import org.onosproject.yang.runtime.RuntimeContext;
import org.slf4j.Logger;
import com.google.common.io.CharStreams;

/**
 * Dynamic config synchronizer provider for NETCONF.
 * <p>
 * <ul>
 * <li> Converts POJO YANG into XML.
 * <li> Adds NETCONF envelope around it.
 * <li> Send request down to the device over NETCONF
 * </ul>
 */
public class NetconfDeviceConfigSynchronizerProvider
        extends AbstractProvider
        implements DeviceConfigSynchronizationProvider {

    private static final Logger log = getLogger(NetconfDeviceConfigSynchronizerProvider.class);

    // TODO this should probably be defined on YRT Serializer side
    /**
     * {@link RuntimeContext} parameter Dataformat specifying XML.
     */
    private static final String DATAFORMAT_XML = "xml";

    private static final String XMLNS_XC = "xmlns:xc";
    private static final String NETCONF_1_0_BASE_NAMESPACE =
                                    "urn:ietf:params:xml:ns:netconf:base:1.0";

    /**
     * Annotation to add xc namespace declaration.
     * {@value #XMLNS_XC}={@value #NETCONF_1_0_BASE_NAMESPACE}
     */
    private static final DefaultAnnotation XMLNS_XC_ANNOTATION =
                    new DefaultAnnotation(XMLNS_XC, NETCONF_1_0_BASE_NAMESPACE);

    private static final String XC_OPERATION = "xc:operation";


    private NetconfContext context;

    // FIXME remove and let netconf southbound deal with message-id generation
    private final AtomicInteger messageId = new AtomicInteger(1);

    protected NetconfDeviceConfigSynchronizerProvider(ProviderId id,
                                                      NetconfContext context) {
        super(id);
        this.context = checkNotNull(context);
    }

    @Override
    public CompletableFuture<SetResponse> setConfiguration(DeviceId deviceId,
                                                           SetRequest request) {
        // sanity check and handle empty change?

        // TODOs:
        // - Construct convert request object into XML
        // --  [FutureWork] may need to introduce behaviour for Device specific
        //     workaround insertion

        StringBuilder rpc = new StringBuilder();

        // - Add NETCONF envelope
        rpc.append("<rpc xmlns=\"").append(NETCONF_1_0_BASE_NAMESPACE).append("\" ")
            .append("message-id=\"").append(messageId.getAndIncrement()).append("\">");

        rpc.append("<edit-config>");
        rpc.append("<target>");
        // TODO directly writing to running for now
        rpc.append("<running/>");
        rpc.append("</target>\n");
        rpc.append("<config ")
            .append(XMLNS_XC).append("=\"").append(NETCONF_1_0_BASE_NAMESPACE).append("\">");
        // TODO netconf SBI should probably be adding these envelopes once
        // netconf SBI is in better shape
        // TODO In such case netconf sbi need to define namespace externally visible.
        // ("xc" in above instance)
        // to be used to add operations on config tree nodes


        // Convert change(s) into a DataNode tree
        for (Change change : request.changes()) {

            // TODO switch statement can probably be removed
            switch (change.op()) {
            case REPLACE:
            case UPDATE:
            case DELETE:
                // convert DataNode -> ResourceData
                ResourceData data = toResourceData(change);

                // build CompositeData
                DefaultCompositeData.Builder compositeData =
                                        DefaultCompositeData.builder();

                // add ResourceData
                compositeData.resourceData(data);

                // add AnnotatedNodeInfo operation
                compositeData.addAnnotatedNodeInfo(toAnnotatedNodeInfo(change.op(), change.path()));

                RuntimeContext yrtContext = new DefaultRuntimeContext.Builder()
                                           .setDataFormat(DATAFORMAT_XML)
                                           .addAnnotation(XMLNS_XC_ANNOTATION)
                                           .build();
                CompositeStream xml = context.yangRuntime().encode(compositeData.build(),
                                                                   yrtContext);
                try {
                    CharStreams.copy(new InputStreamReader(xml.resourceData(), UTF_8), rpc);
                } catch (IOException e) {
                    log.error("IOException thrown", e);
                    // FIXME handle error
                }
                break;

            default:
                log.error("Should never reach here. {}", change);
                break;
            }
        }

        // - close NETCONF envelope
        // TODO eventually these should be handled by NETCONF SBI side
        rpc.append('\n');
        rpc.append("</config>");
        rpc.append("</edit-config>");
        rpc.append("</rpc>");

        // - send requests down to the device
        NetconfSession session = getNetconfSession(deviceId);
        if (session == null) {
            log.error("No session available for {}", deviceId);
            return completedFuture(SetResponse.response(request,
                                                        Code.FAILED_PRECONDITION,
                                                        "No session for " + deviceId));
        }
        try {
            // FIXME Netconf async API is currently screwed up, need to fix
            // NetconfSession, etc.
            CompletableFuture<String> response = session.request(rpc.toString());
            log.info("TRACE: request:\n{}", XmlString.prettifyXml(rpc));
            return response.handle((resp, err) -> {
                if (err == null) {
                    log.info("TRACE: reply:\n{}", XmlString.prettifyXml(resp));
                    // FIXME check response properly
                    return SetResponse.ok(request);
                } else {
                    return SetResponse.response(request, Code.UNKNOWN, err.getMessage());
                }
            });
        } catch (NetconfException e) {
            // TODO Handle error
            log.error("NetconfException thrown", e);
            return completedFuture(SetResponse.response(request, Code.UNKNOWN, e.getMessage()));

        }
    }

    // overridable for ease of testing
    /**
     * Returns a session for the specified deviceId.
     *
     * @param deviceId for which we wish to retrieve a session
     * @return a NetconfSession with the specified node
     * or null if this node does not have the session to the specified Device.
     */
    protected NetconfSession getNetconfSession(DeviceId deviceId) {
        NetconfDevice device = context.netconfController().getNetconfDevice(deviceId);
        checkNotNull(device, "The specified deviceId could not be found by the NETCONF controller.");
        NetconfSession session = device.getSession();
        checkNotNull(session, "A session could not be retrieved for the specified deviceId.");
        return session;
    }

    /**
     * Creates AnnotatedNodeInfo for {@code node}.
     *
     * @param op operation
     * @param parent resourceId
     * @param node the node
     * @return AnnotatedNodeInfo
     */
    static AnnotatedNodeInfo annotatedNodeInfo(Operation op,
                                               ResourceId parent,
                                               DataNode node) {
        return DefaultAnnotatedNodeInfo.builder()
                .resourceId(ResourceIds.resourceId(parent, node))
                .addAnnotation(toAnnotation(op))
                .build();
    }

    /**
     * Creates AnnotatedNodeInfo for specified resource path.
     *
     * @param op operation
     * @param path resourceId
     * @return AnnotatedNodeInfo
     */
    static AnnotatedNodeInfo toAnnotatedNodeInfo(Operation op,
                                               ResourceId path) {
        return DefaultAnnotatedNodeInfo.builder()
                .resourceId(path)
                .addAnnotation(toAnnotation(op))
                .build();
    }

    /**
     * Transform DataNode into a ResourceData.
     *
     * @param change object
     * @return ResourceData
     */
    static ResourceData toResourceData(Change change) {
        DefaultResourceData.Builder builder = DefaultResourceData.builder();
        builder.resourceId(change.path());
        if (change.op() != Change.Operation.DELETE) {
            DataNode dataNode = change.val();
            if (dataNode instanceof InnerNode) {
                ((InnerNode) dataNode).childNodes().values().forEach(builder::addDataNode);
            } else {
                log.error("Unexpected DataNode encountered", change);
            }
        }

        return builder.build();
    }

    static Annotation toAnnotation(Operation op) {
        switch (op) {
        case DELETE:
            return new DefaultAnnotation(XC_OPERATION, "remove");
        case REPLACE:
            return new DefaultAnnotation(XC_OPERATION, "replace");
        case UPDATE:
            return new DefaultAnnotation(XC_OPERATION, "merge");
        default:
            throw new IllegalArgumentException("Unknown operation " + op);
        }
    }

}
