/*
 * Copyright 2014-2015 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;
    }
}
