/*
 * Copyright 2014 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.sdnip.cli;

import java.util.Collection;

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.sdnip.SdnIpService;
import org.onosproject.sdnip.bgp.BgpSession;

/**
 * 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() {
        SdnIpService service = get(SdnIpService.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;
    }
}
