/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * 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 com.google.common.collect.Lists;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.onlab.packet.ChassisId;
import org.onlab.packet.MacAddress;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
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 java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.lang.Integer.parseInt;
import static org.onosproject.net.DefaultAnnotations.Builder;
import static org.onosproject.net.Device.Type.ROUTER;
import static org.onosproject.net.Port.Type.COPPER;
import static org.onosproject.net.PortNumber.portNumber;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * 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 ETH = "Ethernet";
    private static final String MBPS = "mbps";
    private static final String NAME = "name";
    private static final String IF_LO_ENCAP = "logical-interface.encapsulation";
    private static final String IF_LO_NAME = "logical-interface.name";
    private static final String IF_LO_ADD =
            "logical-interface.address-family.interface-address.ifa-local";
    private static final String LO_INDEX = "local-index";
    private static final String STATUS = "admin-status";
    private static final String SNMP_INDEX = "snmp-index";
    private static final String IF_LO_INDEX = "logical-interface.local-index";
    private static final String IF_LO_STATUS =
            "logical-interface.if-config-flags.iff-up";
    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 REGEX_ADD =
            ".*Private base address\\s*([:,0-9,a-f,A-F]*).*";
    private static final Pattern ADD_PATTERN =
            Pattern.compile(REGEX_ADD, Pattern.DOTALL);

    private static final String JUNIPER = "JUNIPER";
    private static final String UNKNOWN = "UNKNOWN";
    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;
    }

    /**
     * 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 = Lists.newArrayList();
        List<HierarchicalConfiguration> subtrees =
                cfg.configurationsAt(IF_INFO);
        for (HierarchicalConfiguration interfInfo : subtrees) {
            List<HierarchicalConfiguration> interfaceTree =
                    interfInfo.configurationsAt(IF_PHY);
            for (HierarchicalConfiguration interf : interfaceTree) {
                if (interf != null) {
                    if (interf.getString(IF_TYPE) != null &&
                            interf.getString(SPEED) != null) {
                        if (interf.getString(IF_TYPE).contains(ETH) &&
                                interf.getString(SPEED).contains(MBPS)) {
                            portDescriptions.add(parseDefaultPort(interf));
                        } else {
                            log.debug("Ignoring default port candidate {}",
                                      interf.getString(NAME));
                        }
                    } else if (interf.getString(IF_LO_ENCAP) != null &&
                            !interf.getString(NAME).contains("pfe") &&
                            interf.getString(IF_LO_ENCAP).contains("ENET2")) {
                        portDescriptions.add(parseLogicalPort(interf));
                    } else if (interf.getString(NAME).contains("lo")) {
                        portDescriptions.add(parseLoopback(interf));
                    } else {
                        log.debug("Ignoring unknown port {}",
                                  interf.getString(NAME));
                    }
                }
            }
        }
        return portDescriptions;
    }

    private static PortDescription parseLoopback(HierarchicalConfiguration cfg) {
        String name = cfg.getString(IF_LO_NAME).trim();
        PortNumber portNumber = portNumber(name.replace("lo0.", ""));

        Builder annotationsBuilder = DefaultAnnotations.builder()
                .set(AnnotationKeys.PORT_NAME, name);
        String ip = cfg.getString(IF_LO_ADD);
        if (ip != null) {
            annotationsBuilder.set("ip", ip);
        }

        return new DefaultPortDescription(portNumber,
                                          true,
                                          COPPER,
                                          DEFAULT_PORT_SPEED,
                                          annotationsBuilder.build());
    }

    private static DefaultPortDescription parseDefaultPort(HierarchicalConfiguration cfg) {
        PortNumber portNumber = portNumber(cfg.getString(LO_INDEX));
        boolean enabled = "up".equals(cfg.getString(STATUS));
        int speed = parseInt(cfg.getString(SPEED).replaceAll(MBPS, ""));


        Builder annotationsBuilder = DefaultAnnotations.builder()
                .set(AnnotationKeys.PORT_NAME, cfg.getString(NAME).trim());
        setIpIfPresent(cfg, annotationsBuilder);

        return new DefaultPortDescription(portNumber,
                                          enabled,
                                          COPPER,
                                          speed,
                                          annotationsBuilder.build());
    }

    private static DefaultPortDescription parseLogicalPort(HierarchicalConfiguration cfg) {

        String name = cfg.getString(NAME).trim();
        String index = cfg.getString(SNMP_INDEX).trim();
        Builder annotationsBuilder = DefaultAnnotations.builder()
                .set(AnnotationKeys.PORT_NAME, name)
                .set("index", index);
        setIpIfPresent(cfg, annotationsBuilder);

        PortNumber portNumber = PortNumber.portNumber(index);

        boolean enabled = false;
        if (cfg.getString(IF_LO_STATUS) != null) {
            enabled = true;
        }
        //FIXME: port speed should be exposed
        return new DefaultPortDescription(
                portNumber,
                enabled,
                COPPER,
                DEFAULT_PORT_SPEED,
                annotationsBuilder.build());
    }

    private static void setIpIfPresent(HierarchicalConfiguration cfg,
                                       Builder annotationsBuilder) {
        String ip = cfg.getString(IF_LO_ADD);
        if (ip != null) {
            annotationsBuilder.set("ip", ip);
        }
    }

    /**
     * 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));
                int remotePortIndex =
                        neighbor.getInt(LLDP_REM_PORT);
                LinkAbstraction link = new LinkAbstraction(
                        localPortName,
                        mac.toLong(),
                        remotePortIndex);
                neighbour.add(link);
            }
        }
        return neighbour;
    }

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

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