/*
 * Copyright 2017-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.routing.cli;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.commands.Option;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.routing.bgp.BgpInfoService;
import org.onosproject.routing.bgp.BgpSession;

import java.util.Collection;

/**
 * Command to show the BGP neighbors.
 */
@Command(scope = "onos", name = "bgp-neighbors",
         description = "Lists the BGP neighbors")
public class BgpNeighborsListCommand extends AbstractShellCommand {
    @Option(name = "-n", aliases = "--neighbor",
            description = "BGP neighbor to display information about",
            required = false, multiValued = false)
    private String bgpNeighbor;

    private static final String FORMAT_NEIGHBOR_LINE1 =
        "BGP neighbor is %s, remote AS %d, local AS %d";
    private static final String FORMAT_NEIGHBOR_LINE2 =
        "  Remote router ID %s, IP %s, BGP version %d, Hold time %d";
    private static final String FORMAT_NEIGHBOR_LINE3 =
        "  Remote AFI/SAFI IPv4 Unicast %s Multicast %s, IPv6 Unicast %s Multicast %s";
    private static final String FORMAT_NEIGHBOR_LINE4 =
        "  Local  router ID %s, IP %s, BGP version %d, Hold time %d";
    private static final String FORMAT_NEIGHBOR_LINE5 =
        "  Local  AFI/SAFI IPv4 Unicast %s Multicast %s, IPv6 Unicast %s Multicast %s";
    private static final String FORMAT_NEIGHBOR_LINE6 =
        "  4 Octet AS Capability: %s %s";

    @Override
    protected void execute() {
        BgpInfoService service = AbstractShellCommand.get(BgpInfoService.class);
        Collection<BgpSession> bgpSessions = service.getBgpSessions();

        if (bgpNeighbor != null) {
            // Print a single neighbor (if found)
            BgpSession foundBgpSession = null;
            for (BgpSession bgpSession : bgpSessions) {
                if (bgpSession.remoteInfo().bgpId().toString().equals(bgpNeighbor)) {
                    foundBgpSession = bgpSession;
                    break;
                }
            }
            if (foundBgpSession != null) {
                printNeighbor(foundBgpSession);
            } else {
                print("BGP neighbor %s not found", bgpNeighbor);
            }
            return;
        }

        // Print all neighbors
        printNeighbors(bgpSessions);
    }

    /**
     * Prints all BGP neighbors.
     *
     * @param bgpSessions the BGP sessions for the neighbors to print
     */
    private void printNeighbors(Collection<BgpSession> bgpSessions) {
        if (outputJson()) {
            print("%s", json(bgpSessions));
        } else {
            for (BgpSession bgpSession : bgpSessions) {
                printNeighbor(bgpSession);
            }
        }
    }

    /**
     * Prints a BGP neighbor.
     *
     * @param bgpSession the BGP session for the neighbor to print
     */
    private void printNeighbor(BgpSession bgpSession) {
        print(FORMAT_NEIGHBOR_LINE1,
              bgpSession.remoteInfo().bgpId().toString(),
              bgpSession.remoteInfo().asNumber(),
              bgpSession.localInfo().asNumber());
        print(FORMAT_NEIGHBOR_LINE2,
              bgpSession.remoteInfo().bgpId().toString(),
              bgpSession.remoteInfo().address().toString(),
              bgpSession.remoteInfo().bgpVersion(),
              bgpSession.remoteInfo().holdtime());
        print(FORMAT_NEIGHBOR_LINE3,
              bgpSession.remoteInfo().ipv4Unicast() ? "YES" : "NO",
              bgpSession.remoteInfo().ipv4Multicast() ? "YES" : "NO",
              bgpSession.remoteInfo().ipv6Unicast() ? "YES" : "NO",
              bgpSession.remoteInfo().ipv6Multicast() ? "YES" : "NO");
        print(FORMAT_NEIGHBOR_LINE4,
              bgpSession.localInfo().bgpId().toString(),
              bgpSession.localInfo().address().toString(),
              bgpSession.localInfo().bgpVersion(),
              bgpSession.localInfo().holdtime());
        print(FORMAT_NEIGHBOR_LINE5,
              bgpSession.localInfo().ipv4Unicast() ? "YES" : "NO",
              bgpSession.localInfo().ipv4Multicast() ? "YES" : "NO",
              bgpSession.localInfo().ipv6Unicast() ? "YES" : "NO",
              bgpSession.localInfo().ipv6Multicast() ? "YES" : "NO");
        if (bgpSession.localInfo().as4OctetCapability() ||
            bgpSession.remoteInfo().as4OctetCapability()) {
            print(FORMAT_NEIGHBOR_LINE6,
                  bgpSession.localInfo().as4OctetCapability() ? "Advertised" : "",
                  bgpSession.remoteInfo().as4OctetCapability() ? "Received" : "");
        }
    }

    /**
     * Produces a JSON array of BGP neighbors.
     *
     * @param bgpSessions the BGP sessions with the data
     * @return JSON array with the neighbors
     */
    private JsonNode json(Collection<BgpSession> bgpSessions) {
        ObjectMapper mapper = new ObjectMapper();
        ArrayNode result = mapper.createArrayNode();

        for (BgpSession bgpSession : bgpSessions) {
            result.add(json(mapper, bgpSession));
        }
        return result;
    }

    /**
     * Produces JSON object for a BGP neighbor.
     *
     * @param mapper the JSON object mapper to use
     * @param bgpSession the BGP session with the data
     * @return JSON object for the route
     */
    private ObjectNode json(ObjectMapper mapper, BgpSession bgpSession) {
        ObjectNode result = mapper.createObjectNode();

        result.put("remoteAddress", bgpSession.remoteInfo().address().toString());
        result.put("remoteBgpVersion", bgpSession.remoteInfo().bgpVersion());
        result.put("remoteAs", bgpSession.remoteInfo().asNumber());
        result.put("remoteAs4", bgpSession.remoteInfo().as4Number());
        result.put("remoteHoldtime", bgpSession.remoteInfo().holdtime());
        result.put("remoteBgpId", bgpSession.remoteInfo().bgpId().toString());
        result.put("remoteIpv4Unicast", bgpSession.remoteInfo().ipv4Unicast());
        result.put("remoteIpv4Multicast", bgpSession.remoteInfo().ipv4Multicast());
        result.put("remoteIpv6Unicast", bgpSession.remoteInfo().ipv6Unicast());
        result.put("remoteIpv6Multicast", bgpSession.remoteInfo().ipv6Multicast());
        //
        result.put("localAddress", bgpSession.localInfo().address().toString());
        result.put("localBgpVersion", bgpSession.localInfo().bgpVersion());
        result.put("localAs", bgpSession.localInfo().asNumber());
        result.put("localAs4", bgpSession.localInfo().as4Number());
        result.put("localHoldtime", bgpSession.localInfo().holdtime());
        result.put("localBgpId", bgpSession.localInfo().bgpId().toString());
        result.put("localIpv4Unicast", bgpSession.localInfo().ipv4Unicast());
        result.put("localIpv4Multicast", bgpSession.localInfo().ipv4Multicast());
        result.put("localIpv6Unicast", bgpSession.localInfo().ipv6Unicast());
        result.put("localIpv6Multicast", bgpSession.localInfo().ipv6Multicast());

        return result;
    }
}
