/*
 * 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.
 */
package org.onosproject.drivers.ciena.c5170.netconf;

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

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.onlab.packet.ChassisId;
import org.onosproject.drivers.netconf.TemplateManager;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.LinkDiscovery;
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.DefaultPortStatistics;
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceDescriptionDiscovery;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.device.PortStatistics;
import org.onosproject.net.device.PortStatisticsDiscovery;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.link.DefaultLinkDescription;
import org.onosproject.net.link.LinkDescription;
import org.onosproject.netconf.NetconfController;
import org.onosproject.netconf.NetconfException;
import org.onosproject.netconf.NetconfSession;
import org.slf4j.Logger;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * Discovers the ports from a Ciena WaveServer Rest device.
 */
public class Ciena5170DeviceDescription extends AbstractHandlerBehaviour
        implements DeviceDescriptionDiscovery, PortStatisticsDiscovery, LinkDiscovery {
    static final TemplateManager TEMPLATE_MANAGER = new TemplateManager();

    static {
        TEMPLATE_MANAGER.load(Ciena5170DeviceDescription.class, "/templates/requests/%s.j2", "systemInfo",
                "chassis-mac", "softwareVersion", "logicalPorts", "port-stats", "link-info");
    }

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

    @Override
    public DeviceDescription discoverDeviceDetails() {

        DeviceId deviceId = handler().data().deviceId();
        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
        NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession();
        try {
            Node systemInfo = TEMPLATE_MANAGER.doRequest(session, "systemInfo");
            Node chassisMac = TEMPLATE_MANAGER.doRequest(session, "chassis-mac");
            Node softwareVersion = TEMPLATE_MANAGER.doRequest(session, "softwareVersion");
            XPath xp = XPathFactory.newInstance().newXPath();
            String mac = xp.evaluate("lldp-global-operational/chassis-id/text()", chassisMac).toUpperCase();
            return new DefaultDeviceDescription(deviceId.uri(), Device.Type.SWITCH, "Ciena",
                    xp.evaluate("components/component/name/text()", systemInfo),
                    xp.evaluate("software-state/running-package/package-version/text()", softwareVersion), mac,
                    new ChassisId(Long.valueOf(mac, 16)));

        } catch (XPathExpressionException | NetconfException ne) {
            log.error("failed to query system info from device {} : {}", handler().data().deviceId(), ne.getMessage(),
                    ne);
        }

        return new DefaultDeviceDescription(deviceId.uri(), Device.Type.SWITCH, "Ciena", "5170", "Unknown", "Unknown",
                new ChassisId());
    }

    /**
     * Convert the specification of port speed in the of of #unit, i.e. {@10G} to MB
     * as represented by a Long.
     *
     * @param ps
     *            specification of port speed
     * @return port speed as MBs
     */
    private Long portSpeedToLong(String ps) {
        String value = ps.trim();
        StringBuilder digits = new StringBuilder();
        String unit = "";
        for (int i = 0; i < value.length(); i += 1) {
            final char c = value.charAt(i);
            if (Character.isDigit(c)) {
                digits.append(c);
            } else {
                unit = value.substring(i).toUpperCase().trim();
                break;
            }
        }

        switch (unit) {
        case "G":
        case "GB":
            return Long.valueOf(digits.toString()) * 1000;
        case "M":
        case "MB":
        default:
            return Long.valueOf(digits.toString());
        }
    }

    @Override
    public List<PortDescription> discoverPortDetails() {
        List<PortDescription> ports = new ArrayList<PortDescription>();
        DeviceId deviceId = handler().data().deviceId();
        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
        if (controller == null || controller.getDevicesMap() == null
                || controller.getDevicesMap().get(deviceId) == null) {
            log.warn("NETCONF session to device {} not yet established, will be retried", deviceId);
            return ports;
        }
        NetconfSession session = controller.getDevicesMap().get(deviceId).getSession();

        try {
            Node logicalPorts = TEMPLATE_MANAGER.doRequest(session, "logicalPorts");
            XPath xp = XPathFactory.newInstance().newXPath();
            NodeList nl = (NodeList) xp.evaluate("interfaces/interface/config", logicalPorts, XPathConstants.NODESET);
            int count = nl.getLength();
            Node node;
            for (int i = 0; i < count; i += 1) {
                node = nl.item(i);
                if (xp.evaluate("type/text()", node).equals("ettp")) {
                    ports.add(DefaultPortDescription.builder()
                            .withPortNumber(PortNumber.portNumber(xp.evaluate("name/text()", node)))
                            .isEnabled(Boolean.valueOf(xp.evaluate("admin-status/text()", node)))
                            .portSpeed(portSpeedToLong(xp.evaluate("port-speed/text()", node))).type(Port.Type.PACKET)
                            .build());
                }
            }
        } catch (NetconfException | XPathExpressionException e) {
            log.error("Unable to retrieve port information for device {}, {}", deviceId, e);
        }
        return ports;
    }

    @Override
    public Collection<PortStatistics> discoverPortStatistics() {
        List<PortStatistics> stats = new ArrayList<PortStatistics>();

        DeviceId deviceId = handler().data().deviceId();
        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
        if (controller == null || controller.getDevicesMap() == null
                || controller.getDevicesMap().get(deviceId) == null) {
            log.warn("NETCONF session to device {} not yet established, will be retried", deviceId);
            return stats;
        }
        NetconfSession session = controller.getDevicesMap().get(deviceId).getSession();

        try {
            Node data = TEMPLATE_MANAGER.doRequest(session, "port-stats");
            XPath xp = XPathFactory.newInstance().newXPath();
            NodeList interfaces = (NodeList) xp.evaluate("interfaces/interface", data, XPathConstants.NODESET);
            int count = interfaces.getLength();
            for (int i = 0; i < count; i += 1) {
                Node iface = interfaces.item(i);
                if (xp.evaluate("config/type/text()", iface).equals("ettp")) {
                    stats.add(DefaultPortStatistics.builder().setDeviceId(deviceId)
                            .setPort(PortNumber.portNumber(xp.evaluate("name/text()", iface)))
                            .setBytesReceived(Long.valueOf(xp.evaluate("state/counters/in-octets/text()", iface)))
                            .setBytesSent(Long.valueOf(xp.evaluate("state/counters/out-octets/text()", iface)))
                            .setPacketsReceived(Long.valueOf(xp.evaluate("state/counters/in-pkts/text()", iface)))
                            .setPacketsSent(Long.valueOf(xp.evaluate("state/counters/out-pkts/text()", iface)))
                            .setPacketsTxErrors(Long.valueOf(xp.evaluate("state/counters/out-errors/text()", iface)))
                            .setPacketsRxErrors(Long.valueOf(xp.evaluate("state/counters/in-errors/text()", iface)))
                            .build());
                }
            }
        } catch (NetconfException | XPathExpressionException e) {
            log.error("Unable to retrieve port statistics for device {}, {}", deviceId, e);
        }

        return stats;
    }

    @Override
    public Set<LinkDescription> getLinks() {
        log.debug("LINKS CHECKING ...");
        Set<LinkDescription> links = new HashSet<LinkDescription>();
        DeviceId deviceId = handler().data().deviceId();
        NetconfController controller = checkNotNull(handler().get(NetconfController.class));
        if (controller == null || controller.getDevicesMap() == null
                || controller.getDevicesMap().get(deviceId) == null) {
            log.warn("NETCONF session to device {} not yet established, cannot load links, will be retried", deviceId);
            return links;
        }
        NetconfSession session = controller.getDevicesMap().get(deviceId).getSession();
        try {

            DeviceService deviceService = this.handler().get(DeviceService.class);

            Iterable<Device> devices = deviceService.getAvailableDevices();
            Map<String, Device> lookup = new HashMap<String, Device>();
            for (Device d : devices) {
                lookup.put(d.chassisId().toString().toUpperCase(), d);
            }

            Node logicalPorts = TEMPLATE_MANAGER.doRequest(session, "link-info");
            XPath xp = XPathFactory.newInstance().newXPath();
            NodeList ifaces = (NodeList) xp.evaluate("interfaces/interface", logicalPorts, XPathConstants.NODESET);
            int count = ifaces.getLength();
            Node iface;
            Node destChassis;
            for (int i = 0; i < count; i += 1) {
                iface = ifaces.item(i);
                if (xp.evaluate("config/type/text()", iface).equals("ettp")) {
                    destChassis = (Node) xp.evaluate("state/lldp-remote-port-operational/chassis-id", iface,
                            XPathConstants.NODE);

                    if (destChassis != null) {
                        Device dest = lookup.get(destChassis.getTextContent().toUpperCase());

                        if (dest != null) {

                            links.add(new DefaultLinkDescription(
                                    new ConnectPoint(deviceId,
                                            PortNumber.portNumber(xp.evaluate("name/text()", iface))),
                                    new ConnectPoint(dest.id(),
                                            PortNumber.portNumber(xp.evaluate(
                                                    "state/lldp-remote-port-operational/port-id/text()", iface))),
                                    Link.Type.DIRECT, true));
                        } else {
                            log.warn("DEST chassisID not found: chassis {} port {}",
                                    destChassis.getTextContent().toUpperCase(), xp.evaluate("name/text()", iface));
                        }
                    } else {
                        log.debug("NO LINK for {}", xp.evaluate("name/text()", iface));
                    }
                }
            }
        } catch (NetconfException | XPathExpressionException e) {
            log.error("Unable to retrieve links for device {}, {}", deviceId, e);
        }

        return links;
    }

}
