/*
 * Copyright 2018-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.
 *
 * This work was partially supported by EC H2020 project METRO-HAUL (761727).
 */

package org.onosproject.drivers.odtn.openconfig;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;

import org.slf4j.Logger;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.concurrent.CompletableFuture;

import org.onlab.packet.ChassisId;

import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;

import org.onosproject.drivers.utilities.XmlConfigParser;

import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceDescriptionDiscovery;
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.DefaultPortDescription.Builder;
import org.onosproject.net.device.PortDescription;

import org.onosproject.net.driver.AbstractHandlerBehaviour;

import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.Port.Type;
import org.onosproject.net.PortNumber;

import org.onosproject.netconf.NetconfController;
import org.onosproject.netconf.NetconfDevice;
import org.onosproject.netconf.NetconfException;
import org.onosproject.netconf.NetconfSession;

import com.google.common.collect.ImmutableList;

import org.onosproject.odtn.behaviour.OdtnDeviceDescriptionDiscovery;


/**
 * Driver Implementation of the DeviceDescrption discovery for OpenConfig
 * terminal devices.
 *
 */
public class TerminalDeviceDiscovery
    extends AbstractHandlerBehaviour
    implements OdtnDeviceDescriptionDiscovery, DeviceDescriptionDiscovery {

    private static final String RPC_TAG_NETCONF_BASE =
        "<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">";

    private static final String RPC_CLOSE_TAG = "</rpc>";

    private static final String OC_PLATFORM_TYPES_TRANSCEIVER =
        "oc-platform-types:TRANSCEIVER";

    private static final String OC_PLATFORM_TYPES_PORT =
        "oc-platform-types:PORT";

    private static final String OC_TRANSPORT_TYPES_OPTICAL_CHANNEL =
        "oc-opt-types:OPTICAL_CHANNEL";

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


    /**
     * Returns the NetconfSession with the device for which the method was called.
     *
     * @param deviceId device indetifier
     *
     * @return The netconf session or null
     */
    private NetconfSession getNetconfSession(DeviceId deviceId) {
        NetconfController controller = handler().get(NetconfController.class);
        NetconfDevice ncdev = controller.getDevicesMap().get(deviceId);
        if (ncdev == null) {
            log.trace("No netconf device, returning null session");
            return null;
        }
        return ncdev.getSession();
    }


    /**
     * Get the deviceId for which the methods apply.
     *
     * @return The deviceId as contained in the handler data
     */
    private DeviceId did() {
        return handler().data().deviceId();
    }


    /**
     * Get the device instance for which the methods apply.
     *
     * @return The device instance
     */
    private Device getDevice() {
        DeviceService deviceService = checkNotNull(handler().get(DeviceService.class));
        Device device = deviceService.getDevice(did());
        return device;
    }


    /**
     * Construct a String with a Netconf filtered get RPC Message.
     *
     * @param filter A valid XML tree with the filter to apply in the get
     * @return a String containing the RPC XML Document
     */
    private String filteredGetBuilder(String filter) {
        StringBuilder rpc = new StringBuilder(RPC_TAG_NETCONF_BASE);
        rpc.append("<get>");
        rpc.append("<filter type='subtree'>");
        rpc.append(filter);
        rpc.append("</filter>");
        rpc.append("</get>");
        rpc.append(RPC_CLOSE_TAG);
        return rpc.toString();
    }


    /**
     * Construct a String with a Netconf filtered get RPC Message.
     *
     * @param filter A valid XPath Expression with the filter to apply in the get
     * @return a String containing the RPC XML Document
     *
     * Note: server must support xpath capability.

     * <select=" /components/component[name='PORT-A-In-1']/properties/...
     * ...property[name='onos-index']/config/value" type="xpath"/>
     */
    private String xpathFilteredGetBuilder(String filter) {
        StringBuilder rpc = new StringBuilder(RPC_TAG_NETCONF_BASE);
        rpc.append("<get>");
        rpc.append("<filter type='xpath' select=\"");
        rpc.append(filter);
        rpc.append("\"/>");
        rpc.append("</get>");
        rpc.append(RPC_CLOSE_TAG);
        return rpc.toString();
    }


    /**
     * Builds a request to get Device details, operational data.
     *
     * @return A string with the Netconf RPC for a get with subtree rpcing based on
     *    /components/component/state/type being oc-platform-types:OPERATING_SYSTEM
     */
    private String getDeviceDetailsBuilder() {
        StringBuilder filter = new StringBuilder();
        filter.append("<components xmlns='http://openconfig.net/yang/platform'>");
        filter.append(" <component>");
        filter.append("  <state>");
        filter.append("   <type xmlns:oc-platform-types='http://openconfig.net/");
        filter.append("yang/platform-types'>oc-platform-types:OPERATING_SYSTEM</type>");
        filter.append("  </state>");
        filter.append(" </component>");
        filter.append("</components>");
        return filteredGetBuilder(filter.toString());
        /* I am not sure the alternative method is more efficient
           try {
           DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
           DocumentBuilder db = dbf.newDocumentBuilder();
           Document doc = db.newDocument();
           Element rpc = doc.createElementNS("urn:ietf:params:xml:ns:netconf:base:1.0", "rpc");
           Element get = doc.createElement("get");
           Element rpc = doc.createElement("rpc");
           Element components = doc.createElementNS("http://openconfig.net/yang/platform", "components");
           Element component = doc.createElement("component");
           Element state = doc.createElement("state");
           Element type  = doc.createElement("type");
           type.setAttributeNS("http://www.w3.org/2000/xmlns/",
           "xmlns:oc-platform-types", "http://openconfig.net/yang/platform-types");
           type.appendChild(doc.createTextNode("oc-platform-types:OPERATING_SYSTEM"));
           state.appendChild(type);
           component.appendChild(state);
           components.appendChild(component);
           rpc.appendChild(components);
           get.appendChild(rpc);
           rpc.appendChild(get);
           doc.appendChild(rpc);
           return NetconfRpcParserUtil.toString(doc);
           } catch (Exception e) {
           throw new RuntimeException(new NetconfException("Exception in getDeviceDetailsBuilder", e));
           }
         */
    }


    /**
     * Builds a request to get Device Components, config and operational data.
     *
     * @return A string with the Netconf RPC for a get with subtree rpcing based on
     *    /components/
     */
    private String getDeviceComponentsBuilder() {
        return filteredGetBuilder("<components xmlns='http://openconfig.net/yang/platform'/>");
    }


    /**
     * Builds a request to get Device Ports, config and operational data.
     *
     * @return A string with the Netconf RPC for a get with subtree rpcing based on
     *    /components/component/state/type being oc-platform-types:PORT
     */
    private String getDevicePortsBuilder() {
        StringBuilder rpc = new StringBuilder();
        rpc.append("<components xmlns='http://openconfig.net/yang/platform'>");
        rpc.append(" <component><state>");
        rpc.append("   <type xmlns:oc-platform-types='http://openconfig.net/");
        rpc.append("yang/platform-types'>oc-platform-types:PORT</type>");
        rpc.append(" </state></component>");
        rpc.append("</components>");
        return filteredGetBuilder(rpc.toString());
    }


    /**
     * Returns a DeviceDescription with Device info.
     *
     * @return DeviceDescription or null
     *
     * //CHECKSTYLE:OFF
     * <pre>{@code
     * <data>
     * <components xmlns="http://openconfig.net/yang/platform">
     *  <component>
     *   <state>
     *     <name>FIRMWARE</name>
     *     <type>oc-platform-types:OPERATING_SYSTEM</type>
     *     <description>CTTC METRO-HAUL Emulated OpenConfig TerminalDevice</description>
     *     <version>0.0.1</version>
     *   </state>
     *  </component>
     * </components>
     * </data>
     *}</pre>
     * //CHECKSTYLE:ON
     */
    @Override
    public DeviceDescription discoverDeviceDetails() {
        log.info("TerminalDeviceDiscovery::discoverDeviceDetails device {}", did());
        boolean defaultAvailable = true;
        SparseAnnotations annotations = DefaultAnnotations.builder().build();

        // Other option "OTHER", we use ROADM for now
        org.onosproject.net.Device.Type type =
            org.onosproject.net.Device.Type.ROADM;

        // Some defaults
        String vendor       = "NOVENDOR";
        String hwVersion    = "0.1.1";
        String swVersion    = "0.1.1";
        String serialNumber = "0xCAFEBEEF";
        String chassisId    = "128";

        // Get the session,
        NetconfSession session = getNetconfSession(did());
        if (session != null) {
            try {
                String reply = session.get(getDeviceDetailsBuilder());
                // <rpc-reply> as root node
                XMLConfiguration xconf = (XMLConfiguration) XmlConfigParser.loadXmlString(reply);
                vendor       = xconf.getString("data/components/component/state/mfg-name", vendor);
                serialNumber = xconf.getString("data/components/component/state/serial-no", serialNumber);
                // Requires OpenConfig >= 2018
                swVersion    = xconf.getString("data/components/component/state/software-version", swVersion);
                hwVersion    = xconf.getString("data/components/component/state/hardware-version", hwVersion);
            } catch (Exception e) {
                throw new IllegalStateException(new NetconfException("Failed to retrieve version info.", e));
            }
        } else {
            log.info("TerminalDeviceDiscovery::discoverDeviceDetails - No netconf session for {}", did());
        }
        log.info("VENDOR    {}", vendor);
        log.info("HWVERSION {}", hwVersion);
        log.info("SWVERSION {}", swVersion);
        log.info("SERIAL    {}", serialNumber);
        log.info("CHASSISID {}", chassisId);
        ChassisId cid = new ChassisId(Long.valueOf(chassisId, 10));
        return new DefaultDeviceDescription(did().uri(),
                type, vendor, hwVersion, swVersion, serialNumber,
                cid, defaultAvailable, annotations);
    }



    /**
     * Returns a list of PortDescriptions for the device.
     *
     * @return a list of descriptions.
     *
     * The RPC reply follows the following pattern:
     * //CHECKSTYLE:OFF
     * <pre>{@code
     * <?xml version="1.0" encoding="UTF-8"?>
     * <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="7">
     * <data>
     *   <components xmlns="http://openconfig.net/yang/platform">
     *     <component>....
     *     </component>
     *     <component>....
     *     </component>
     *   </components>
     * </data>
     * </rpc-reply>
     * }</pre>
     * //CHECKSTYLE:ON
     */
    @Override
    public List<PortDescription> discoverPortDetails() {
        try {
            NetconfSession session = getNetconfSession(did());
            /*
            Note: the method may get called before the netconf session is established
            2018-05-24 14:01:43,607 | INFO
            event NetworkConfigEvent{time=2018-05-24T14:01:43.602Z, type=CONFIG_ADDED, ....
            configClass=class org.onosproject.netconf.config.NetconfDeviceConfig

            2018-05-24 14:01:43,623 | INFO  | vice-installer-2 | TerminalDeviceDiscovery
            TerminalDeviceDiscovery::discoverPortDetails netconf:127.0.0.1:830

            2018-05-24 14:01:43,624 | ERROR | vice-installer-2 | TerminalDeviceDiscovery
            org.onosproject.onos-drivers-metrohaul - 1.14.0.SNAPSHOT | Exception discoverPortDetails()

            2018-05-24 14:01:43,631 | INFO  | vice-installer-1 | NetconfControllerImpl
            Creating NETCONF session to netconf:127.0.0.1:830 with apache-mina
             */
            if (session == null) {
                log.error("discoverPortDetails called with null session for {}", did());
                return ImmutableList.of();
            }

            CompletableFuture<String> fut = session.rpc(getDeviceComponentsBuilder());
            String rpcReply = fut.get();

            XMLConfiguration xconf = (XMLConfiguration) XmlConfigParser.loadXmlString(rpcReply);
            xconf.setExpressionEngine(new XPathExpressionEngine());

            HierarchicalConfiguration components = xconf.configurationAt("data/components");
            return parsePorts(components);
        } catch (Exception e) {
            log.error("Exception discoverPortDetails() {}", did(), e);
            return ImmutableList.of();
        }
    }




    /**
     * Parses port information from OpenConfig XML configuration.
     *
     * @param components the XML document with components root.
     * @return List of ports
     *
     * //CHECKSTYLE:OFF
     * <pre>{@code
     *   <components xmlns="http://openconfig.net/yang/platform">
     *     <component>....
     *     </component>
     *     <component>....
     *     </component>
     *   </components>
     * }</pre>
     * //CHECKSTYLE:ON
     */
    protected List<PortDescription> parsePorts(HierarchicalConfiguration components) {
        return components.configurationsAt("component")
            .stream()
            .filter(component -> {
                    return !component.getString("name", "unknown")
                            .equals("unknown") &&
                        component.getString("state/type", "unknown")
                            .equals(OC_PLATFORM_TYPES_PORT);
                    })
            .map(component -> {
                try {
                    // Pass the root document for cross-reference
                    return parsePortComponent(component, components);
                } catch (Exception e) {
                    return null;
                }
                })
            .filter(Objects::nonNull)
            .collect(Collectors.toList());
    }


    /**
     * Checks if a given component has a subcomponent of a given type.
     *
     * @param component subtree to parse looking for subcomponents.
     * @param components the full components tree, to cross-ref in
     *  case we need to check (sub)components' types.
     *
     * @return true or false
     */
     private boolean hasSubComponentOfType(
            HierarchicalConfiguration component,
            HierarchicalConfiguration components,
            String type) {
        long count = component.configurationsAt("subcomponents/subcomponent")
            .stream()
            .filter(subcomponent -> {
                    String scName = subcomponent.getString("name");
                    StringBuilder sb = new StringBuilder("component[name='");
                    sb.append(scName);
                    sb.append("']/state/type");
                    String scType = components.getString(sb.toString(), "unknown");
                    return scType.equals(type);
                    })
            .count();
        return (count > 0);
    }


    /**
     * Checks if a given component has a subcomponent of type OPTICAL_CHANNEL.
     *
     * @param component subtree to parse
     * @param components the full components tree, to cross-ref in
     *  case we need to check transceivers or optical channels.
     *
     * @return true or false
     */
     private boolean hasOpticalChannelSubComponent(
             HierarchicalConfiguration component,
             HierarchicalConfiguration components) {
         return hasSubComponentOfType(component, components,
                 OC_TRANSPORT_TYPES_OPTICAL_CHANNEL);
     }


     /**
      *  Checks if a given component has a subcomponent of type TRANSCEIVER.
      *
      * @param component subtree to parse
      * @param components the full components tree, to cross-ref in
      *  case we need to check transceivers or optical channels.
      *
      * @return true or false
      */
     private boolean hasTransceiverSubComponent(
             HierarchicalConfiguration component,
             HierarchicalConfiguration components) {
         return hasSubComponentOfType(component, components,
                 OC_PLATFORM_TYPES_TRANSCEIVER);
     }


     /**
      * Parses a component XML doc into a PortDescription.
      *
      * @param component subtree to parse. It must be a component ot type PORT.
      * @param components the full components tree, to cross-ref in
      *  case we need to check transceivers or optical channels.
      *
      * @return PortDescription or null if component does not have onos-index
      */
     private PortDescription parsePortComponent(
             HierarchicalConfiguration component,
             HierarchicalConfiguration components) {
         Map<String, String> annotations = new HashMap<>();
         String name = component.getString("name");
         String type = component.getString("state/type");
         log.info("Parsing Component {} type {}", name, type);
         annotations.put(OdtnDeviceDescriptionDiscovery.OC_NAME, name);
         annotations.put(OdtnDeviceDescriptionDiscovery.OC_TYPE, type);

         // Store all properties as port properties
         component.configurationsAt("properties/property")
             .forEach(property -> {
                     String pn = property.getString("name");
                     String pv = property.getString("state/value");
                     annotations.put(pn, pv);
                     });

         if (!annotations.containsKey(ONOS_PORT_INDEX)) {
             log.warn("DEBUG: PORT {} does not include onos-index, skipping", name);
             return null;
         }

         // The heuristic to know if it is client or line side
         if (!annotations.containsKey(PORT_TYPE)) {
             if (hasTransceiverSubComponent(component, components)) {
                 annotations.put(PORT_TYPE, OdtnPortType.CLIENT.value());
             } else if (hasOpticalChannelSubComponent(component, components)) {
                 annotations.put(PORT_TYPE, OdtnPortType.LINE.value());
             }
         }

         // Build the port
         Builder builder = DefaultPortDescription.builder();
         builder.withPortNumber(PortNumber.portNumber(
                     Long.parseLong(annotations.get(ONOS_PORT_INDEX)), name));
         if (annotations.get(PORT_TYPE)
                 .equals(OdtnPortType.CLIENT.value())) {
             log.info("Adding CLIENT port");
             builder.type(Type.PACKET);
         } else if (annotations.get(PORT_TYPE)
                 .equals(OdtnPortType.LINE.value())) {
             log.info("Adding LINE port");
             builder.type(Type.OCH);
         } else {
             log.info("Unknown port added as CLIENT port");
         }
         builder.annotations(DefaultAnnotations.builder().putAll(annotations).build());
         return builder.build();
     }
}
