/*
 * 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.cli.net;

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.onosproject.cli.AbstractShellCommand;
import org.onosproject.incubator.net.routing.ResolvedRoute;
import org.onosproject.incubator.net.routing.Route;
import org.onosproject.incubator.net.routing.RouteInfo;
import org.onosproject.incubator.net.routing.RouteService;
import org.onosproject.incubator.net.routing.RouteTableId;

import java.util.Collection;
import java.util.Comparator;
import java.util.Objects;
import java.util.Optional;

/**
 * Command to show the routes in the routing tables.
 */
@Command(scope = "onos", name = "routes",
        description = "Lists routes in the route store")
public class RoutesListCommand extends AbstractShellCommand {

    private static final String NETWORK = "Network";
    private static final String NEXTHOP = "Next Hop";
    private static final String SOURCE = "Source";

    private static final String FORMAT_ROUTE = "%-1s   %-18s %-15s %-10s";
    private static final String FORMAT_ROUTE6 = "%-1s   %-43s %-39s %-10s";

    private static final String FORMAT_TABLE = "Table: %s";
    private static final String FORMAT_TOTAL = "   Total: %d";

    @Override
    protected void execute() {
        RouteService service = AbstractShellCommand.get(RouteService.class);

        if (outputJson()) {
            ObjectMapper mapper = new ObjectMapper();
            ObjectNode result = mapper.createObjectNode();
            result.set("routes4", json(service.getRoutes(new RouteTableId("ipv4"))));
            result.set("routes6", json(service.getRoutes(new RouteTableId("ipv6"))));
            print("%s", result);
        } else {
            service.getRouteTables().forEach(id -> {
                Collection<RouteInfo> tableRoutes = service.getRoutes(id);

                String format = tableRoutes.stream().anyMatch(route -> route.prefix().isIp6()) ?
                        FORMAT_ROUTE6 : FORMAT_ROUTE;

                // Print header
                print(FORMAT_TABLE, id);
                print(format, "", NETWORK, NEXTHOP, SOURCE);

                // Print routing entries
                tableRoutes.stream()
                        .sorted(Comparator.comparing(r -> r.prefix().address()))
                        .forEach(route -> this.print(format, route));

                print(FORMAT_TOTAL, tableRoutes.size());
                print("");
            });
        }
    }

    private void print(String format, RouteInfo routeInfo) {
        routeInfo.allRoutes()
                .forEach(r -> print(format, isBestRoute(routeInfo.bestRoute(), r) ? ">" : "",
                        r.prefix(), r.nextHop(), Route.Source.UNDEFINED));
    }



    private boolean isBestRoute(Optional<ResolvedRoute> bestRoute, ResolvedRoute route) {
        return Objects.equals(bestRoute.orElse(null), route);
    }

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

        routes.stream()
                .flatMap(ri -> ri.allRoutes().stream())
                .forEach(r -> result.add(json(mapper, r)));

        return result;
    }

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

        result.put("prefix", route.prefix().toString());
        result.put("nextHop", route.nextHop().toString());

        return result;
    }

}
