/*
 * Copyright 2016-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.juniper;

import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.lang.StringUtils;
import org.onlab.packet.ChassisId;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultAnnotations.Builder;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.Port.Type;
import org.onosproject.net.behaviour.ControllerInfo;
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.link.DefaultLinkDescription;
import org.onosproject.net.link.LinkDescription;
import org.slf4j.Logger;

import com.google.common.base.Strings;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.onosproject.drivers.juniper.StaticRoute.DEFAULT_METRIC_STATIC_ROUTE;
import static org.onosproject.drivers.juniper.StaticRoute.toFlowRulePriority;
import static org.onosproject.net.Device.Type.ROUTER;
import static org.onosproject.net.PortNumber.portNumber;
import static org.slf4j.LoggerFactory.getLogger;

// Ref: Junos YANG:
//   https://github.com/Juniper/yang

/**
 * Utility class for Netconf XML for Juniper.
 * Tested with MX240 junos 14.2
 */
public final class JuniperUtils {

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

    public static final String FAILED_CFG = "Failed to retrieve configuration.";

    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>";

    //requests
    public static final String REQ_LLDP_NBR_INFO = "<get-lldp-neighbors-information/>";
    public static final String REQ_SYS_INFO = "<get-system-information/>";
    public static final String REQ_MAC_ADD_INFO = "<get-chassis-mac-addresses/>";
    public static final String REQ_IF_INFO = "<get-interface-information/>";

    //helper strings for parsing
    private static final String LLDP_LIST_NBR_INFO = "lldp-neighbors-information";
    private static final String LLDP_NBR_INFO = "lldp-neighbor-information";
    private static final String SYS_INFO = "system-information";
    private static final String HW_MODEL = "hardware-model";
    private static final String OS_NAME = "os-name";
    private static final String OS_VER = "os-version";
    private static final String SER_NUM = "serial-number";
    private static final String IF_INFO = "interface-information";
    private static final String IF_PHY = "physical-interface";

    private static final String IF_TYPE = "if-type";
    private static final String SPEED = "speed";
    private static final String NAME = "name";
    private static final String PORT = "port";
    private static final String PROTOCOL = "protocol";

    private static final String TCP = "tcp";

    // seems to be unique index within device
    private static final String SNMP_INDEX = "snmp-index";

    private static final String LLDP_LO_PORT = "lldp-local-port-id";
    private static final String LLDP_REM_CHASS = "lldp-remote-chassis-id";
    private static final String LLDP_REM_PORT = "lldp-remote-port-id";
    private static final String LLDP_REM_PORT_DES = "lldp-remote-port-description";
    private static final String REGEX_ADD =
            ".*Private base address\\s*([:,0-9,a-f,A-F]*).*";
    private static final Pattern ADD_PATTERN =
            Pattern.compile(REGEX_ADD, Pattern.DOTALL);

    public static final String PROTOCOL_NAME = "protocol-name";

    private static final String JUNIPER = "JUNIPER";
    private static final String UNKNOWN = "UNKNOWN";

    /**
     * Annotation key for interface type.
     */
    static final String AK_IF_TYPE = "ifType";

    /**
     * Annotation key for Logical link-layer encapsulation.
     */
    static final String AK_ENCAPSULATION = "encapsulation";

    /**
     * Annotation key for interface description.
     */
    static final String AK_DESCRIPTION = "description";

    /**
     * Annotation key for interface admin status. "up"/"down"
     */
    static final String AK_ADMIN_STATUS = "adminStatus";

    /**
     * Annotation key for interface operational status. "up"/"down"
     */
    static final String AK_OPER_STATUS = "operStatus";

    /**
     * Annotation key for logical-interfaces parent physical interface name.
     */
    static final String AK_PHYSICAL_PORT_NAME = "physicalPortName";


    private static final String NUMERIC_SPEED_REGEXP = "(\\d+)([GM])bps";

    /**
     * {@value #NUMERIC_SPEED_REGEXP} as {@link Pattern}.
     * Case insensitive
     */
    private static final Pattern SPEED_PATTERN =
            Pattern.compile(NUMERIC_SPEED_REGEXP, Pattern.CASE_INSENSITIVE);

    /**
     * Default port speed {@value} Mbps.
     */
    private static final long DEFAULT_PORT_SPEED = 1000;


    private JuniperUtils() {
        //not called, preventing any allocation
    }

    /**
     * Helper method to build a XML schema given a request.
     *
     * @param request a tag element of the XML schema
     * @return string containing the XML schema
     */
    public static String requestBuilder(String request) {
        return RPC_TAG_NETCONF_BASE +
                request + RPC_CLOSE_TAG;
    }

    /**
     * Helper method to commit a config.
     *
     * @return string contains the result of the commit
     */
    public static String commitBuilder() {
        return RPC_TAG_NETCONF_BASE +
                "<commit/>" + RPC_CLOSE_TAG;
    }

    /**
     * Helper method to build the schema for returning to a previously
     * committed configuration.
     *
     * @param versionToReturn Configuration to return to. The range of values is from 0 through 49.
     *                        The most recently saved configuration is number 0,
     *                        and the oldest saved configuration is number 49.
     * @return string containing the XML schema
     */
    public static String rollbackBuilder(int versionToReturn) {
        return RPC_TAG_NETCONF_BASE +
                "<get-rollback-information>" +
                "<rollback>" + versionToReturn + "</rollback>" +
                "</get-rollback-information>" +
                RPC_CLOSE_TAG;
    }


    /**
     * Helper method to build an XML schema to configure a static route
     * given a {@link StaticRoute}.
     *
     * @param staticRoute the static route to be configured
     * @return string contains the result of the configuration
     */
    public static String routeAddBuilder(StaticRoute staticRoute) {
        StringBuilder rpc = new StringBuilder("<configuration>\n");
        rpc.append("<routing-options>\n");
        rpc.append("<static>\n");
        rpc.append("<route>\n");
        rpc.append("<destination>" + staticRoute.ipv4Dst().toString() + "</destination>\n");
        rpc.append("<next-hop>" + staticRoute.nextHop() + "</next-hop>\n");

        if (staticRoute.getMetric() != DEFAULT_METRIC_STATIC_ROUTE) {
            rpc.append("<metric>" + staticRoute.getMetric() + "</metric>");
        }

        rpc.append("</route>\n");
        rpc.append("</static>\n");
        rpc.append("</routing-options>\n");
        rpc.append("</configuration>\n");

        return rpc.toString();
    }

    /**
     * Helper method to build a XML schema to delete a static route
     * given a {@link StaticRoute}.
     * @param staticRoute the static route to be deleted
     * @return string contains the result of the configuratio
     */
    public static String routeDeleteBuilder(StaticRoute staticRoute) {
        return "<configuration>\n" +
        "<routing-options>\n" +
        "<static>\n" +
        "<route operation=\"delete\">\n" +
        "<name>" + staticRoute.ipv4Dst().toString() + "</name>\n" +
        "</route>\n" +
        "</static>\n" +
        "</routing-options>\n" +
        "</configuration>\n";
    }


    /**
     * Parses device configuration and returns the device description.
     *
     * @param deviceId    the id of the device
     * @param sysInfoCfg  system configuration
     * @param chassisText chassis string
     * @return device description
     */
    public static DeviceDescription parseJuniperDescription(DeviceId deviceId,
                                                            HierarchicalConfiguration sysInfoCfg,
                                                            String chassisText) {
        HierarchicalConfiguration info = sysInfoCfg.configurationAt(SYS_INFO);

        String hw = info.getString(HW_MODEL) == null ? UNKNOWN : info.getString(HW_MODEL);
        String sw = UNKNOWN;
        if (info.getString(OS_NAME) != null || info.getString(OS_VER) != null) {
            sw = info.getString(OS_NAME) + " " + info.getString(OS_VER);
        }
        String serial = info.getString(SER_NUM) == null ? UNKNOWN : info.getString(SER_NUM);

        Matcher matcher = ADD_PATTERN.matcher(chassisText);
        if (matcher.lookingAt()) {
            String chassis = matcher.group(1);
            MacAddress chassisMac = MacAddress.valueOf(chassis);
            return new DefaultDeviceDescription(deviceId.uri(), ROUTER,
                                                JUNIPER, hw, sw, serial,
                                                new ChassisId(chassisMac.toLong()),
                                                DefaultAnnotations.EMPTY);
        }
        return new DefaultDeviceDescription(deviceId.uri(), ROUTER,
                                            JUNIPER, hw, sw, serial,
                                            null, DefaultAnnotations.EMPTY);
    }

    /**
     * Parses device ports configuration and returns a list of
     * port description.
     *
     * @param cfg interface configuration
     * @return list of interface descriptions of the device
     */
    public static List<PortDescription> parseJuniperPorts(HierarchicalConfiguration cfg) {
        //This methods ignores some internal ports

        List<PortDescription> portDescriptions = new ArrayList<>();
        List<HierarchicalConfiguration> subtrees =
                cfg.configurationsAt(IF_INFO);
        for (HierarchicalConfiguration interfInfo : subtrees) {
            List<HierarchicalConfiguration> interfaceTree =
                    interfInfo.configurationsAt(IF_PHY);
            for (HierarchicalConfiguration phyIntf : interfaceTree) {
                if (phyIntf == null) {
                    continue;
                }
                // parse physical Interface
                parsePhysicalInterface(portDescriptions, phyIntf);
            }
        }
        return portDescriptions;
    }

    /**
     * Parses {@literal physical-interface} tree.
     *
     * @param portDescriptions list to populate Ports found parsing configuration
     * @param phyIntf physical-interface
     */
    private static void parsePhysicalInterface(List<PortDescription> portDescriptions,
                                               HierarchicalConfiguration phyIntf) {
        Builder annotations = DefaultAnnotations.builder();
        PortNumber portNumber = portNumber(phyIntf.getString(SNMP_INDEX));
        String phyPortName = phyIntf.getString(NAME);
        if (portNumber == null) {
            log.debug("Skipping physical-interface {}, no PortNumer",
                      phyPortName);
            log.trace("  {}", phyIntf);
            return;
        }

        setIfNonNull(annotations,
                     AnnotationKeys.PORT_NAME,
                     phyPortName);

        setIfNonNull(annotations,
                     AnnotationKeys.PORT_MAC,
                     phyIntf.getString("current-physical-address"));

        setIfNonNull(annotations,
                     AK_IF_TYPE,
                     phyIntf.getString(IF_TYPE));

        setIfNonNull(annotations,
                     AK_DESCRIPTION,
                     phyIntf.getString("description"));

        boolean opUp = phyIntf.getString("oper-status", "down").equals("up");
        annotations.set(AK_OPER_STATUS, toUpDown(opUp));

        boolean admUp = phyIntf.getString("admin-status", "down").equals("up");
        annotations.set(AK_ADMIN_STATUS, toUpDown(admUp));

        long portSpeed = toMbps(phyIntf.getString(SPEED));

        portDescriptions.add(DefaultPortDescription.builder()
                .withPortNumber(portNumber)
                .isEnabled(admUp && opUp)
                .type(Type.COPPER)
                .portSpeed(portSpeed)
                .annotations(annotations.build()).build());

        // parse each logical Interface
        for (HierarchicalConfiguration logIntf : phyIntf.configurationsAt("logical-interface")) {
            if (logIntf == null) {
                continue;
            }
            PortNumber lPortNumber = safePortNumber(logIntf.getString(SNMP_INDEX));
            if (lPortNumber == null) {
                log.debug("Skipping logical-interface {} under {}, no PortNumer",
                          logIntf.getString(NAME), phyPortName);
                log.trace("  {}", logIntf);
                continue;
            }

            Builder lannotations = DefaultAnnotations.builder();
            setIfNonNull(lannotations,
                         AnnotationKeys.PORT_NAME,
                         logIntf.getString(NAME));
            setIfNonNull(lannotations,
                         AK_PHYSICAL_PORT_NAME,
                         phyPortName);

            String afName = logIntf.getString("address-family.address-family-name");
            String address = logIntf.getString("address-family.interface-address.ifa-local");
            if (afName != null && address != null) {
                // e.g., inet : IPV4, inet6 : IPV6
                setIfNonNull(lannotations, afName, address);
            }

            // preserving former behavior
            setIfNonNull(lannotations,
                         "ip",
                         logIntf.getString("address-family.interface-address.ifa-local"));

            setIfNonNull(lannotations,
                         AK_ENCAPSULATION, logIntf.getString("encapsulation"));

            // TODO confirm if this is correct.
            // Looking at sample data,
            // it seemed all logical loop-back interfaces were down
            boolean lEnabled = logIntf.getString("if-config-flags.iff-up") != null;

            portDescriptions.add(DefaultPortDescription.builder()
                    .withPortNumber(lPortNumber)
                    .isEnabled(admUp && opUp && lEnabled)
                    .type(Type.COPPER)
                    .portSpeed(portSpeed).annotations(lannotations.build())
                    .build());
        }
    }

    /**
     * Port status as "up"/"down".
     *
     * @param portStatus port status
     * @return "up" if {@code portStats} is {@literal true}, "down" otherwise
     */
    static String toUpDown(boolean portStatus) {
        return portStatus ? "up" : "down";
    }

    /**
     * Translate interface {@literal speed} value as Mbps value.
     *
     * Note: {@literal Unlimited} and unrecognizable string will be treated as
     *  {@value #DEFAULT_PORT_SPEED} Mbps.
     *
     * @param speed in String
     * @return Mbps
     */
    static long toMbps(String speed) {
        String s = Strings.nullToEmpty(speed).trim().toLowerCase();
        Matcher matcher = SPEED_PATTERN.matcher(s);
        if (matcher.matches()) {
            // numeric
            long n = Long.parseLong(matcher.group(1));
            String unit = matcher.group(2);
            if ("m".equalsIgnoreCase(unit)) {
                // Mbps
                return n;
            } else {
                // assume Gbps
                return 1000 * n;
            }
        }
        log.trace("Treating unknown speed value {} as default", speed);
        // Unlimited or unrecognizable
        return DEFAULT_PORT_SPEED;
    }

    /**
     * Sets annotation entry if {@literal value} was not {@literal null}.
     *
     * @param builder Annotation Builder
     * @param key Annotation key
     * @param value Annotation value (can be {@literal null})
     */
    static void setIfNonNull(Builder builder, String key, String value) {
        if (value != null) {
            builder.set(key, value.trim());
        }
    }

    /**
     * Creates PortNumber instance from String.
     *
     * Instead for throwing Exception, it will return null on format error.
     *
     * @param s port number as string
     * @return PortNumber instance or null on error
     */
    static PortNumber safePortNumber(String s) {
        try {
            return portNumber(s);
        } catch (RuntimeException e) {
            log.trace("Failed parsing PortNumber {}", s, e);
        }
        return null;
    }

    /**
     * Create two LinkDescriptions corresponding to the bidirectional links.
     *
     * @param localDevId  the identity of the local device
     * @param localPort   the port of the local device
     * @param remoteDevId the identity of the remote device
     * @param remotePort  the port of the remote device
     * @param descs       the collection to which the link descriptions
     *                    should be added
     */
    public static void createBiDirLinkDescription(DeviceId localDevId,
                                                  Port localPort,
                                                  DeviceId remoteDevId,
                                                  Port remotePort,
                                                  Set<LinkDescription> descs) {

        ConnectPoint local = new ConnectPoint(localDevId, localPort.number());
        ConnectPoint remote = new ConnectPoint(remoteDevId, remotePort.number());
        DefaultAnnotations annotations = DefaultAnnotations.builder()
                .set("layer", "IP")
                .build();
        descs.add(new DefaultLinkDescription(
                local, remote, Link.Type.INDIRECT, false, annotations));
        descs.add(new DefaultLinkDescription(
                remote, local, Link.Type.INDIRECT, false, annotations));
    }

    /**
     * Parses neighbours discovery information and returns a list of
     * link abstractions.
     *
     * @param info interface configuration
     * @return set of link abstractions
     */
    public static Set<LinkAbstraction> parseJuniperLldp(HierarchicalConfiguration info) {
        Set<LinkAbstraction> neighbour = new HashSet<>();
        List<HierarchicalConfiguration> subtrees =
                info.configurationsAt(LLDP_LIST_NBR_INFO);
        for (HierarchicalConfiguration neighborsInfo : subtrees) {
            List<HierarchicalConfiguration> neighbors =
                    neighborsInfo.configurationsAt(LLDP_NBR_INFO);
            for (HierarchicalConfiguration neighbor : neighbors) {
                String localPortName = neighbor.getString(LLDP_LO_PORT);
                MacAddress mac = MacAddress.valueOf(
                        neighbor.getString(LLDP_REM_CHASS));
                long remotePortIndex =
                        neighbor.getInt(LLDP_REM_PORT, -1);
                String remotePortDescription = neighbor.getString(LLDP_REM_PORT_DES, null);
                LinkAbstraction link = new LinkAbstraction(
                        localPortName,
                        mac.toLong(),
                        remotePortIndex,
                        remotePortDescription);
                neighbour.add(link);
            }
        }
        return neighbour;
    }

    /**
     * Device representation of the adjacency at the IP Layer.
     */
    static final class LinkAbstraction {
        protected String localPortName;
        protected ChassisId remoteChassisId;
        protected long remotePortIndex;
        protected String remotePortDescription;

        protected LinkAbstraction(String pName, long chassisId, long pIndex, String pDescription) {
            this.localPortName = pName;
            this.remoteChassisId = new ChassisId(chassisId);
            this.remotePortIndex = pIndex;
            this.remotePortDescription = pDescription;
        }
    }

    enum OperationType {
        ADD,
        REMOVE,
    }

    /**
     * Parses {@literal route-information} tree.
     * This implementation supports only static routes.
     *
     * @param cfg route-information
     * @return a collection of static routes
     */
    public static Collection<StaticRoute> parseRoutingTable(HierarchicalConfiguration cfg) {

        Collection<StaticRoute> staticRoutes = new HashSet<>();
        HierarchicalConfiguration routeInfo =
                cfg.configurationAt("route-information");
        List<HierarchicalConfiguration> routeTables = routeInfo.configurationsAt("route-table");
        for (HierarchicalConfiguration routeTable : routeTables) {
            List<HierarchicalConfiguration> routes = routeTable.configurationsAt("rt");
            for (HierarchicalConfiguration route : routes) {
                if (route != null) {
                    HierarchicalConfiguration rtEntry = route.configurationAt("rt-entry");
                    if (rtEntry.getString(PROTOCOL_NAME) != null &&
                            rtEntry.getString(PROTOCOL_NAME).contains("Static")) {
                        parseStaticRoute(rtEntry,
                                route.getString("rt-destination"),
                                rtEntry.getString("metric"))
                                .ifPresent(x -> staticRoutes.add(x));

                    }
                }
            }
        }
        return staticRoutes;
    }

    /**
     * Parse the {@literal rt-entry} for static routes.
     *
     * @param rtEntry     rt-entry filtered by {@literal protocol-name} equals to Static
     * @param destination rt-destination
     * @return optional of static route
     */
    private static Optional<StaticRoute> parseStaticRoute(HierarchicalConfiguration rtEntry,
                                                          String destination, String metric) {

        Ip4Prefix ipDst = Ip4Prefix.valueOf(destination);

        HierarchicalConfiguration nextHop = rtEntry.configurationAt("nh");
        String to = nextHop.getString("to");
        if (StringUtils.isEmpty(to)) {
            return Optional.empty();
        }
        Ip4Address nextHopIp = Ip4Address.valueOf(to);

        if (metric == null) {
            return Optional.of(new StaticRoute(ipDst, nextHopIp, false));
        } else {
            return Optional.of(new StaticRoute(ipDst, nextHopIp, false,
                    toFlowRulePriority(Integer.parseInt(metric))));
        }
    }

    /**
     * Helper method to build a XML schema for a given "set/merge" Op inJunOS XML Format.
     *
     * @param request a CLI command
     * @return string containing the XML schema
     */
    public static String cliSetRequestBuilder(StringBuilder request) {
        StringBuilder rpc = new StringBuilder(RPC_TAG_NETCONF_BASE);
        rpc.append("<edit-config>");
        rpc.append("<target><candidate/></target><config>");
        rpc.append("<configuration>");
        rpc.append(request);
        rpc.append("</configuration>");
        rpc.append("</config></edit-config>");
        rpc.append(RPC_CLOSE_TAG);
        rpc.append("]]>]]>");
        return rpc.toString();
    }

    /**
     * Helper method to build a XML schema for a given "delete Op" in JunOS XML Format.
     *
     * @param request a CLI command
     * @return string containing the XML schema
     */
    public static String cliDeleteRequestBuilder(StringBuilder request) {
        StringBuilder rpc = new StringBuilder(RPC_TAG_NETCONF_BASE);
        rpc.append("<edit-config>");
        rpc.append("<target><candidate/></target>");
        rpc.append("<default-operation>none</default-operation>");
        rpc.append("<config>");
        rpc.append("<configuration>");
        rpc.append(request);
        rpc.append("</configuration>");
        rpc.append("</config></edit-config>");
        rpc.append(RPC_CLOSE_TAG);
        rpc.append("]]>]]>");
        return rpc.toString();
    }

    public static List<ControllerInfo> getOpenFlowControllersFromConfig(HierarchicalConfiguration cfg) {
        List<ControllerInfo> controllers = new ArrayList<ControllerInfo>();
        String ipKey = "configuration.protocols.openflow.mode.ofagent-mode.controller.ip";

        if (!cfg.configurationsAt(ipKey).isEmpty()) {
            List<HierarchicalConfiguration> ipNodes = cfg.configurationsAt(ipKey);

            ipNodes.forEach(ipNode -> {
                int port = 0;
                String proto = UNKNOWN;
                HierarchicalConfiguration protocolNode = ipNode.configurationAt(PROTOCOL);
                HierarchicalConfiguration tcpNode = protocolNode.configurationAt(TCP);

                if (!tcpNode.isEmpty()) {
                    String portString = tcpNode.getString(PORT);

                    if (portString != null && !portString.isEmpty()) {
                        port = Integer.parseInt(portString);
                    }

                    proto = TCP;
                }

                String ipaddress = ipNode.getString(NAME);

                if (ipaddress == null) {
                    ipaddress = UNKNOWN;
                }

                if (ipaddress.equals(UNKNOWN) || proto.equals(UNKNOWN) || port == 0) {
                    log.error("Controller infomation is invalid. Skip this controller node." +
                                    " ipaddress: {}, proto: {}, port: {}", ipaddress, proto, port);
                    return;
                }

                controllers.add(new ControllerInfo(IpAddress.valueOf(ipaddress), port, proto));
            });
        } else {
            log.error("Controller not present");
        }

        return controllers;
    }
}
