/*
 * Copyright 2017-present Open Networking Foundation
 *
 * 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.routeservice.impl;

import com.google.common.collect.ImmutableSet;
import com.googlecode.concurrenttrees.common.KeyValuePair;
import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory;
import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree;
import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.util.GuavaCollectors;
import org.onlab.util.Tools;
import org.onosproject.routeservice.ResolvedRoute;
import org.onosproject.routeservice.RouteEvent;
import org.onosproject.routeservice.RouteTableId;

import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import static org.onosproject.routeservice.RouteTools.createBinaryString;

/**
 * Stores routes that have been resolved.
 */
public class DefaultResolvedRouteStore implements ResolvedRouteStore {

    private Map<RouteTableId, RouteTable> routeTables;
    private static final RouteTableId IPV4 = new RouteTableId("ipv4");
    private static final RouteTableId IPV6 = new RouteTableId("ipv6");

    /**
     * Creates a new resolved route store.
     */
    public DefaultResolvedRouteStore() {
        routeTables = new ConcurrentHashMap<>();

        routeTables.put(IPV4, new RouteTable());
        routeTables.put(IPV6, new RouteTable());
    }

    @Override
    public RouteEvent updateRoute(ResolvedRoute route, Set<ResolvedRoute> alternatives) {
        return getDefaultRouteTable(route).update(route, alternatives);
    }

    @Override
    public RouteEvent removeRoute(IpPrefix prefix) {
        RouteTable table = getDefaultRouteTable(prefix.address());
        return table.remove(prefix);
    }

    @Override
    public Set<RouteTableId> getRouteTables() {
        return routeTables.keySet();
    }

    @Override
    public Collection<ResolvedRoute> getRoutes(RouteTableId table) {
        RouteTable routeTable = routeTables.get(table);
        if (routeTable == null) {
            return Collections.emptySet();
        }
        return routeTable.getRoutes();
    }

    @Override
    public Optional<ResolvedRoute> getRoute(IpPrefix prefix) {
        return getDefaultRouteTable(prefix.address()).getRoute(prefix);
    }

    @Override
    public Collection<ResolvedRoute> getAllRoutes(IpPrefix prefix) {
        return getDefaultRouteTable(prefix.address()).getAllRoutes(prefix);
    }

    @Override
    public Optional<ResolvedRoute> longestPrefixMatch(IpAddress ip) {
        return getDefaultRouteTable(ip).longestPrefixMatch(ip);
    }

    private RouteTable getDefaultRouteTable(ResolvedRoute route) {
        return getDefaultRouteTable(route.prefix().address());
    }

    private RouteTable getDefaultRouteTable(IpAddress ip) {
        RouteTableId routeTableId = (ip.isIp4()) ? IPV4 : IPV6;
        return routeTables.get(routeTableId);
    }

    /**
     * Route table into which routes can be placed.
     */
    private class RouteTable {
        private final InvertedRadixTree<ResolvedRoute> routeTable;
        private final Map<IpPrefix, Set<ResolvedRoute>> alternativeRoutes;

        /**
         * Creates a new route table.
         */
        public RouteTable() {
            routeTable = new ConcurrentInvertedRadixTree<>(
                    new DefaultByteArrayNodeFactory());

            alternativeRoutes = new ConcurrentHashMap<>();
        }

        /**
         * Adds or updates the route in the route table.
         *
         * @param route route to update
         * @param alternatives alternative routes
         */
        public RouteEvent update(ResolvedRoute route, Set<ResolvedRoute> alternatives) {
            Set<ResolvedRoute> immutableAlternatives = checkAlternatives(route, alternatives);

                ResolvedRoute oldRoute = routeTable.put(createBinaryString(route.prefix()), route);
                Set<ResolvedRoute> oldRoutes = alternativeRoutes.put(route.prefix(), immutableAlternatives);

                if (!route.equals(oldRoute)) {
                    if (oldRoute == null) {
                        return new RouteEvent(RouteEvent.Type.ROUTE_ADDED, route,
                                immutableAlternatives);
                    } else {
                        return new RouteEvent(RouteEvent.Type.ROUTE_UPDATED, route,
                                oldRoute, immutableAlternatives, oldRoutes);
                    }
                }

                if (!immutableAlternatives.equals(oldRoutes)) {
                    return new RouteEvent(RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED,
                            route, null, immutableAlternatives, oldRoutes);
                }

                return null;
        }

        /**
         * Checks that the best route is present in the alternatives list and
         * returns an immutable set of alternatives.
         *
         * @param route best route
         * @param alternatives alternatives
         * @return immutable set of alternative routes
         */
        private Set<ResolvedRoute> checkAlternatives(ResolvedRoute route, Set<ResolvedRoute> alternatives) {
            if (!alternatives.contains(route)) {
                return ImmutableSet.<ResolvedRoute>builder()
                        .addAll(alternatives)
                        .add(route)
                        .build();
            } else {
                return ImmutableSet.copyOf(alternatives);
            }
        }

        /**
         * Removes the route from the route table.
         *
         * @param prefix prefix to remove
         */
        public RouteEvent remove(IpPrefix prefix) {
            String key = createBinaryString(prefix);

            ResolvedRoute route = routeTable.getValueForExactKey(key);
            Set<ResolvedRoute> alternatives = alternativeRoutes.remove(prefix);

            if (route != null) {
                routeTable.remove(key);
                return new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, route, alternatives);
            }
            return null;
        }

        /**
         * Returns all routes in the route table.
         *
         * @return all routes
         */
        public Collection<ResolvedRoute> getRoutes() {
            return Tools.stream(routeTable.getKeyValuePairsForKeysStartingWith(""))
                    .map(KeyValuePair::getValue)
                    .collect(GuavaCollectors.toImmutableList());
        }

        /**
         * Returns the best route for the given prefix, if one exists.
         *
         * @param prefix IP prefix
         * @return best route
         */
        public Optional<ResolvedRoute> getRoute(IpPrefix prefix) {
            return Optional.ofNullable(routeTable.getValueForExactKey(createBinaryString(prefix)));
        }

        public Collection<ResolvedRoute> getAllRoutes(IpPrefix prefix) {
            return alternativeRoutes.getOrDefault(prefix, Collections.emptySet());
        }

        /**
         * Performs a longest prefix match with the given IP in the route table.
         *
         * @param ip IP address to look up
         * @return most specific prefix containing the given
         */
        public Optional<ResolvedRoute> longestPrefixMatch(IpAddress ip) {
            return Tools.stream(routeTable.getValuesForKeysPrefixing(createBinaryString(ip.toIpPrefix())))
                    .reduce((a, b) -> b); // reduces to the last element in the stream
        }
    }
}
