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

import com.google.common.collect.ImmutableList;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
import org.onlab.packet.ChassisId;
import org.onosproject.drivers.utilities.XmlConfigParser;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port.Type;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.DefaultPortDescription.Builder;
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceDescriptionDiscovery;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.netconf.NetconfController;
import org.onosproject.netconf.NetconfDevice;
import org.onosproject.netconf.NetconfSession;
import org.onosproject.odtn.behaviour.OdtnDeviceDescriptionDiscovery;
import org.slf4j.Logger;

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

import static org.slf4j.LoggerFactory.getLogger;


/**
 * Driver Implementation of the DeviceDescrption discovery for OpenConfig
 * terminal devices.
 *
 */
public class CassiniTerminalDeviceDiscovery
    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(CassiniTerminalDeviceDiscovery.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();
    }


    /**
     * 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();
    }


    /**
     * 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 getTerminalDeviceBuilder() {
        return filteredGetBuilder("<terminal-device xmlns='http://openconfig.net/yang/terminal-device'/>");
    }


    @Override
    public DeviceDescription discoverDeviceDetails() {
        return new DefaultDeviceDescription(handler().data().deviceId().uri(),
                                            Device.Type.OTN,
                                            "EDGECORE",
                                            "Cassini",
                                            "OcNOS",
                                            "",
                                            new ChassisId("1"));
    }



    /**
     * 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());
            if (session == null) {
                log.error("discoverPortDetails called with null session for {}", did());
                return ImmutableList.of();
            }

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

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

            HierarchicalConfiguration logicalChannels = xconf.configurationAt("data/terminal-device/logical-channels");
            return parseLogicalChannels(logicalChannels);
        } catch (Exception e) {
            log.error("Exception discoverPortDetails() {}", did(), e);
            return ImmutableList.of();
        }
    }




    /**
     * Parses transceiver information from OpenConfig XML configuration.
     *
     * @param terminalDevice 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> parseLogicalChannels(HierarchicalConfiguration terminalDevice) {
        return terminalDevice.configurationsAt("channel")
            .stream()
            .filter(channel -> !channel.getString("index", "unknown").equals("unknown"))
            .map(channel -> {
                try {
                    // Pass the root document for cross-reference
                    return parseLogicalChannel(channel);
                } catch (Exception e) {
                    return null;
                }
                })
            .filter(Objects::nonNull)
            .collect(Collectors.toList());
    }


     /**
      * Parses a component XML doc into a PortDescription.
      *
      * @param channel subtree to parse. It must be a component ot type PORT.
      *  case we need to check transceivers or optical channels.
      *
      * @return PortDescription or null if component does not have onos-index
      */
     private PortDescription parseLogicalChannel(
             HierarchicalConfiguration channel) {

         HierarchicalConfiguration config = channel.configurationAt("config");
         String name = config.getString("index");
         String portName = config.getString("description");
         String rateClass = config.getString("rate-class");
         log.info("Parsing Component {} type {} rate {}", name, portName, rateClass);

         Map<String, String> annotations = new HashMap<>();
         annotations.put(OdtnDeviceDescriptionDiscovery.OC_NAME, name);
         annotations.put(OdtnDeviceDescriptionDiscovery.OC_TYPE, portName);

         // Store all properties as port properties

         Pattern clientPattern = Pattern.compile("ce(\\d*)/1"); // e.g. ce1/1
         Pattern linePattern = Pattern.compile("oe(\\d*)"); // e.g. oe1
         Matcher clientMatch = clientPattern.matcher(portName);
         Matcher lineMatch = linePattern.matcher(portName);

         Pattern portSpeedPattern = Pattern.compile("TRIB_RATE_([0-9.]*)G");
         Matcher portSpeedMatch = portSpeedPattern.matcher(rateClass);


         Builder builder = DefaultPortDescription.builder();

         if (clientMatch.find()) {
             Long num = Long.parseLong(clientMatch.group(1));
             Long portNum = 100 + num;
             String connectionId = "connection:" + num.toString();

             annotations.putIfAbsent(PORT_TYPE, OdtnPortType.CLIENT.value());
             annotations.putIfAbsent(ONOS_PORT_INDEX, portNum.toString());
             annotations.putIfAbsent(CONNECTION_ID, connectionId);

             builder.withPortNumber(PortNumber.portNumber(portNum, name));
             builder.type(Type.PACKET);
         } else if (lineMatch.find()) {
             Long num = Long.parseLong(lineMatch.group(1));
             Long portNum = 200 + num;
             String connectionId = "connection:" + num.toString();

             annotations.putIfAbsent(PORT_TYPE, OdtnPortType.LINE.value());
             annotations.putIfAbsent(ONOS_PORT_INDEX, portNum.toString());
             annotations.putIfAbsent(CONNECTION_ID, connectionId);

             builder.withPortNumber(PortNumber.portNumber(portNum, name));
             builder.type(Type.OCH);
         }

         if (portSpeedMatch.find()) {
             Long speed = Long.parseLong(portSpeedMatch.group(1));
             builder.portSpeed(speed * 1000);
         }

         builder.annotations(DefaultAnnotations.builder().putAll(annotations).build());
         return builder.build();
     }
}
