/*
 * Copyright 2016-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.segmentrouting;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.RemovalCause;
import com.google.common.cache.RemovalNotification;
import com.google.common.collect.Sets;

import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.HostLocation;
import org.onosproject.net.PortNumber;
import org.onosproject.net.host.HostEvent;
import org.onosproject.routeservice.ResolvedRoute;
import org.onosproject.routeservice.RouteEvent;
import org.onosproject.net.DeviceId;
import org.onosproject.routeservice.RouteInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Handles RouteEvent and manages routing entries.
 */
public class RouteHandler {
    private static final Logger log = LoggerFactory.getLogger(RouteHandler.class);
    private final SegmentRoutingManager srManager;

    private static final int WAIT_TIME_MS = 1000;
    /**
     * The routeEventCache is implemented to avoid race condition by giving more time to the
     * underlying flow subsystem to process previous populateSubnet call.
     */
    private Cache<IpPrefix, RouteEvent> routeEventCache = CacheBuilder.newBuilder()
            .expireAfterWrite(WAIT_TIME_MS, TimeUnit.MILLISECONDS)
            .removalListener((RemovalNotification<IpPrefix, RouteEvent> notification) -> {
                IpPrefix prefix = notification.getKey();
                RouteEvent routeEvent = notification.getValue();
                RemovalCause cause = notification.getCause();
                log.debug("routeEventCache removal event. prefix={}, routeEvent={}, cause={}",
                        prefix, routeEvent, cause);

                switch (notification.getCause()) {
                    case REPLACED:
                    case EXPIRED:
                        dequeueRouteEvent(routeEvent);
                        break;
                    default:
                        break;
                }
            }).build();

    RouteHandler(SegmentRoutingManager srManager) {
        this.srManager = srManager;

        Executors.newSingleThreadScheduledExecutor()
                .scheduleAtFixedRate(routeEventCache::cleanUp, 0, WAIT_TIME_MS, TimeUnit.MILLISECONDS);
    }

    protected void init(DeviceId deviceId) {
        srManager.routeService.getRouteTables().forEach(routeTableId ->
            srManager.routeService.getRoutes(routeTableId).forEach(routeInfo ->
                routeInfo.allRoutes().forEach(resolvedRoute ->
                    srManager.nextHopLocations(resolvedRoute).stream()
                            .filter(location -> deviceId.equals(location.deviceId()))
                            .forEach(location -> processRouteAddedInternal(resolvedRoute)
                    )
                )
            )
        );
    }

    void processRouteAdded(RouteEvent event) {
        enqueueRouteEvent(event);
    }

    private void processRouteAddedInternal(ResolvedRoute route) {
        processRouteAddedInternal(Sets.newHashSet(route));
    }

    private void processRouteAddedInternal(Collection<ResolvedRoute> routes) {
        if (!isReady()) {
            log.info("System is not ready. Skip adding route for {}", routes);
            return;
        }

        log.info("processRouteAddedInternal. routes={}", routes);

        Set<ConnectPoint> allLocations = Sets.newHashSet();
        Set<IpPrefix> allPrefixes = Sets.newHashSet();
        routes.forEach(route -> {
            allLocations.addAll(srManager.nextHopLocations(route));
            allPrefixes.add(route.prefix());
        });
        log.debug("RouteAdded. populateSubnet {}, {}", allLocations, allPrefixes);
        srManager.defaultRoutingHandler.populateSubnet(allLocations, allPrefixes);

        routes.forEach(route -> {
            IpPrefix prefix = route.prefix();
            MacAddress nextHopMac = route.nextHopMac();
            VlanId nextHopVlan = route.nextHopVlan();
            Set<ConnectPoint> locations = srManager.nextHopLocations(route);

            locations.forEach(location -> {
                log.debug("RouteAdded. addSubnet {}, {}", location, prefix);
                srManager.deviceConfiguration.addSubnet(location, prefix);
                log.debug("RouteAdded populateRoute {}, {}, {}, {}", location, prefix, nextHopMac, nextHopVlan);
                srManager.defaultRoutingHandler.populateRoute(location.deviceId(), prefix,
                        nextHopMac, nextHopVlan, location.port());
            });
        });
    }

    void processRouteUpdated(RouteEvent event) {
        enqueueRouteEvent(event);
    }

    void processAlternativeRoutesChanged(RouteEvent event) {
        enqueueRouteEvent(event);
    }

    private void processRouteUpdatedInternal(Set<ResolvedRoute> routes, Set<ResolvedRoute> oldRoutes) {
        if (!isReady()) {
            log.info("System is not ready. Skip updating route for {} -> {}", oldRoutes, routes);
            return;
        }

        log.info("processRouteUpdatedInternal. routes={}, oldRoutes={}", routes, oldRoutes);

        Set<ConnectPoint> allLocations = Sets.newHashSet();
        Set<IpPrefix> allPrefixes = Sets.newHashSet();
        routes.forEach(route -> {
            allLocations.addAll(srManager.nextHopLocations(route));
            allPrefixes.add(route.prefix());
        });
        log.debug("RouteUpdated. populateSubnet {}, {}", allLocations, allPrefixes);
        srManager.defaultRoutingHandler.populateSubnet(allLocations, allPrefixes);

        Set<ResolvedRoute> toBeRemoved = Sets.difference(oldRoutes, routes).immutableCopy();
        Set<ResolvedRoute> toBeAdded = Sets.difference(routes, oldRoutes).immutableCopy();

        toBeRemoved.forEach(route -> {
            srManager.nextHopLocations(route).forEach(oldLocation -> {
                if (toBeAdded.stream().map(srManager::nextHopLocations)
                        .flatMap(Set::stream).map(ConnectPoint::deviceId)
                        .noneMatch(deviceId -> deviceId.equals(oldLocation.deviceId()))) {
                    IpPrefix prefix = route.prefix();
                    log.debug("RouteUpdated. removeSubnet {}, {}", oldLocation, prefix);
                    srManager.deviceConfiguration.removeSubnet(oldLocation, prefix);
                    // We don't remove the flow on the old location in occasion of two next hops becoming one
                    // since the populateSubnet will point the old location to the new location via spine.
                }
            });
        });

        toBeAdded.forEach(route -> {
            IpPrefix prefix = route.prefix();
            MacAddress nextHopMac = route.nextHopMac();
            VlanId nextHopVlan = route.nextHopVlan();
            Set<ConnectPoint> locations = srManager.nextHopLocations(route);

            locations.forEach(location -> {
                log.debug("RouteUpdated. addSubnet {}, {}", location, prefix);
                srManager.deviceConfiguration.addSubnet(location, prefix);
                log.debug("RouteUpdated. populateRoute {}, {}, {}, {}", location, prefix, nextHopMac, nextHopVlan);
                srManager.defaultRoutingHandler.populateRoute(location.deviceId(), prefix,
                        nextHopMac, nextHopVlan, location.port());
            });
        });
    }

    void processRouteRemoved(RouteEvent event) {
        enqueueRouteEvent(event);
    }

    private void processRouteRemovedInternal(Collection<ResolvedRoute> routes) {
        if (!isReady()) {
            log.info("System is not ready. Skip removing route for {}", routes);
            return;
        }

        log.info("processRouteRemovedInternal. routes={}", routes);

        Set<IpPrefix> allPrefixes = Sets.newHashSet();
        routes.forEach(route -> {
            allPrefixes.add(route.prefix());
        });
        log.debug("RouteRemoved. revokeSubnet {}", allPrefixes);
        srManager.defaultRoutingHandler.revokeSubnet(allPrefixes);

        routes.forEach(route -> {
            IpPrefix prefix = route.prefix();
            MacAddress nextHopMac = route.nextHopMac();
            VlanId nextHopVlan = route.nextHopVlan();
            Set<ConnectPoint> locations = srManager.nextHopLocations(route);

            locations.forEach(location -> {
                log.debug("RouteRemoved. removeSubnet {}, {}", location, prefix);
                srManager.deviceConfiguration.removeSubnet(location, prefix);
                // We don't need to call revokeRoute again since revokeSubnet will remove the prefix
                // from all devices, including the ones that next hop attaches to.

                // Also remove redirection flows on the pair device if exists.
                Optional<DeviceId> pairDeviceId = srManager.getPairDeviceId(location.deviceId());
                Optional<PortNumber> pairLocalPort = srManager.getPairLocalPorts(location.deviceId());
                if (pairDeviceId.isPresent() && pairLocalPort.isPresent()) {
                    // NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
                    //       when the host is untagged
                    VlanId vlanId = Optional.ofNullable(srManager.getInternalVlanId(location)).orElse(nextHopVlan);

                    log.debug("RouteRemoved. revokeRoute {}, {}, {}, {}", location, prefix, nextHopMac, nextHopVlan);
                    srManager.defaultRoutingHandler.revokeRoute(pairDeviceId.get(), prefix,
                            nextHopMac, vlanId, pairLocalPort.get());
                }
            });
        });
    }

    void processHostMovedEvent(HostEvent event) {
        log.info("processHostMovedEvent {}", event);
        MacAddress hostMac = event.subject().mac();
        VlanId hostVlanId = event.subject().vlan();

        affectedRoutes(hostMac, hostVlanId).forEach(affectedRoute -> {
            IpPrefix prefix = affectedRoute.prefix();
            Set<HostLocation> prevLocations = event.prevSubject().locations();
            Set<HostLocation> newLocations = event.subject().locations();

            // For each old location
            Sets.difference(prevLocations, newLocations).stream().filter(srManager::isMasterOf)
                    .forEach(prevLocation -> {
                // Redirect the flows to pair link if configured
                // Note: Do not continue removing any rule
                Optional<DeviceId> pairDeviceId = srManager.getPairDeviceId(prevLocation.deviceId());
                Optional<PortNumber> pairLocalPort = srManager.getPairLocalPorts(prevLocation.deviceId());
                if (pairDeviceId.isPresent() && pairLocalPort.isPresent() && newLocations.stream()
                        .anyMatch(location -> location.deviceId().equals(pairDeviceId.get()))) {
                    // NOTE: Since the pairLocalPort is trunk port, use assigned vlan of original port
                    //       when the host is untagged
                    VlanId vlanId = Optional.ofNullable(srManager.getInternalVlanId(prevLocation)).orElse(hostVlanId);
                    log.debug("HostMoved. populateRoute {}, {}, {}, {}", prevLocation, prefix, hostMac, vlanId);
                    srManager.defaultRoutingHandler.populateRoute(prevLocation.deviceId(), prefix,
                            hostMac, vlanId, pairLocalPort.get());
                    return;
                }

                // No pair information supplied. Remove route
                log.debug("HostMoved. revokeRoute {}, {}, {}, {}", prevLocation, prefix, hostMac, hostVlanId);
                srManager.defaultRoutingHandler.revokeRoute(prevLocation.deviceId(), prefix,
                        hostMac, hostVlanId, prevLocation.port());
            });

            // For each new location, add all new IPs.
            Sets.difference(newLocations, prevLocations).stream().filter(srManager::isMasterOf)
                    .forEach(newLocation -> {
                log.debug("HostMoved. populateRoute {}, {}, {}, {}", newLocation, prefix, hostMac, hostVlanId);
                srManager.defaultRoutingHandler.populateRoute(newLocation.deviceId(), prefix,
                        hostMac, hostVlanId, newLocation.port());
            });

        });
    }

    private Set<ResolvedRoute> affectedRoutes(MacAddress mac, VlanId vlanId) {
        return srManager.routeService.getRouteTables().stream()
                .map(routeTableId -> srManager.routeService.getRoutes(routeTableId))
                .flatMap(Collection::stream)
                .map(RouteInfo::allRoutes)
                .flatMap(Collection::stream)
                .filter(resolvedRoute -> mac.equals(resolvedRoute.nextHopMac()) &&
                        vlanId.equals(resolvedRoute.nextHopVlan())).collect(Collectors.toSet());
    }

    private boolean isReady() {
        return Objects.nonNull(srManager.deviceConfiguration) &&
                Objects.nonNull(srManager.defaultRoutingHandler);
    }

    void enqueueRouteEvent(RouteEvent routeEvent) {
        log.debug("Enqueue routeEvent {}", routeEvent);
        routeEventCache.put(routeEvent.subject().prefix(), routeEvent);
    }

    void dequeueRouteEvent(RouteEvent routeEvent) {
        log.debug("Dequeue routeEvent {}", routeEvent);
        switch (routeEvent.type()) {
            case ROUTE_ADDED:
                processRouteAddedInternal(routeEvent.alternatives());
                break;
            case ROUTE_REMOVED:
                processRouteRemovedInternal(routeEvent.alternatives());
                break;
            case ROUTE_UPDATED:
            case ALTERNATIVE_ROUTES_CHANGED:
                processRouteUpdatedInternal(Sets.newHashSet(routeEvent.alternatives()),
                        Sets.newHashSet(routeEvent.prevAlternatives()));
                break;
            default:
                break;
        }
    }
}
