/*
 * 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 {
    private 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.error("DEST CHASSIS is NULL for {}", 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;
    }

}
