/*
 * 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.routing.fibinstaller;

import com.google.common.collect.ConcurrentHashMultiset;
import com.google.common.collect.Maps;
import com.google.common.collect.Multiset;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Modified;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.util.Tools;
import org.onosproject.app.ApplicationService;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.incubator.net.config.basics.McastConfig;
import org.onosproject.incubator.net.intf.Interface;
import org.onosproject.incubator.net.intf.InterfaceService;
import org.onosproject.incubator.net.routing.ResolvedRoute;
import org.onosproject.incubator.net.routing.Route;
import org.onosproject.incubator.net.routing.RouteEvent;
import org.onosproject.incubator.net.routing.RouteListener;
import org.onosproject.incubator.net.routing.RouteService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.config.basics.SubjectFactories;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flowobjective.DefaultFilteringObjective;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.DefaultNextObjective;
import org.onosproject.net.flowobjective.DefaultObjectiveContext;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.NextObjective;
import org.onosproject.net.flowobjective.ObjectiveContext;
import org.onosproject.routing.InterfaceProvisionRequest;
import org.onosproject.routing.NextHop;
import org.onosproject.routing.NextHopGroupKey;
import org.onosproject.routing.Router;
import org.onosproject.routing.RouterInfo;
import org.onosproject.routing.RoutingService;
import org.onosproject.routing.config.RouterConfigHelper;
import org.onosproject.routing.config.RoutersConfig;
import org.onosproject.routing.config.RoutingConfigurationService;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Dictionary;
import java.util.Map;
import java.util.Set;

/**
 * Programs routes to a single OpenFlow switch.
 */
@Component(immediate = true)
public class FibInstaller {

    private final Logger log = LoggerFactory.getLogger(getClass());
    private static final String APP_NAME = "org.onosproject.fibinstaller";

    private static final int PRIORITY_OFFSET = 100;
    private static final int PRIORITY_MULTIPLIER = 5;

    // FIXME: This should be eliminated when we have an API in SR that
    //        programs the fabric switches for VR
    public static final short ASSIGNED_VLAN = 4094;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected CoreService coreService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected RouteService routeService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected InterfaceService interfaceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected NetworkConfigService networkConfigService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected NetworkConfigRegistry networkConfigRegistry;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ComponentConfigService componentConfigService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected FlowObjectiveService flowObjectiveService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DeviceService deviceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ApplicationService applicationService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected RoutingConfigurationService rs;

    @Property(name = "routeToNextHop", boolValue = false,
            label = "Install a /32 or /128 route to each next hop")
    private boolean routeToNextHop = false;

    // Device id of data-plane switch - should be learned from config
    private DeviceId deviceId;

    private Router interfaceManager;

    private ApplicationId coreAppId;
    private ApplicationId routerAppId;
    private ApplicationId fibAppId;

    // Reference count for how many times a next hop is used by a route
    private final Multiset<IpAddress> nextHopsCount = ConcurrentHashMultiset.create();

    // Mapping from prefix to its current next hop
    private final Map<IpPrefix, IpAddress> prefixToNextHop = Maps.newHashMap();

    // Mapping from next hop IP to next hop object containing group info
    private final Map<IpAddress, Integer> nextHops = Maps.newHashMap();

    private final InternalRouteListener routeListener = new InternalRouteListener();
    private final InternalNetworkConfigListener configListener = new InternalNetworkConfigListener();

    private ConfigFactory<ApplicationId, McastConfig> mcastConfigFactory =
            new ConfigFactory<ApplicationId, McastConfig>(SubjectFactories.APP_SUBJECT_FACTORY,
                    McastConfig.class, "multicast") {
                @Override
                public McastConfig createConfig() {
                    return new McastConfig();
                }
            };

    @Activate
    protected void activate(ComponentContext context) {
        componentConfigService.registerProperties(getClass());
        modified(context);

        coreAppId = coreService.registerApplication(CoreService.CORE_APP_NAME);
        routerAppId = coreService.registerApplication(RoutingService.ROUTER_APP_ID);
        fibAppId = coreService.registerApplication(APP_NAME);

        networkConfigRegistry.registerConfigFactory(mcastConfigFactory);

        networkConfigService.addListener(configListener);

        processRouterConfig();

        applicationService.registerDeactivateHook(fibAppId, () -> cleanUp());

        log.info("Started");
    }

    @Deactivate
    protected void deactivate() {
        networkConfigService.removeListener(configListener);

        componentConfigService.unregisterProperties(getClass(), false);

        log.info("Stopped");
    }

    @Modified
    protected void modified(ComponentContext context) {
        Dictionary<?, ?> properties = context.getProperties();
        if (properties == null) {
            return;
        }

        String strRouteToNextHop = Tools.get(properties, "routeToNextHop");
        routeToNextHop = Boolean.parseBoolean(strRouteToNextHop);

        log.info("routeToNextHop set to {}", routeToNextHop);
    }

    private void processRouterConfig() {
        Set<RoutersConfig.Router> routerConfigs =
                RouterConfigHelper.getRouterConfigurations(networkConfigService, routerAppId);
        if (routerConfigs.isEmpty()) {
            log.info("Router config not available");
            return;
        }
        RoutersConfig.Router routerConfig = routerConfigs.stream().findFirst().get();

        if (interfaceManager == null) {
            deviceId = routerConfig.controlPlaneConnectPoint().deviceId();
            log.info("Router device ID is {}", deviceId);

            routeService.addListener(routeListener);

            interfaceManager = createRouter(RouterInfo.from(routerConfig));
        } else {
            interfaceManager.changeConfiguration(RouterInfo.from(routerConfig), false);
        }
    }

    /**
     * Removes filtering objectives and routes before deactivate.
     */
    private void cleanUp() {
        //remove the route listener
        routeService.removeListener(routeListener);

        //clean up the routes.
        prefixToNextHop.entrySet().stream()
                .map(e -> new Route(Route.Source.UNDEFINED, e.getKey(), e.getValue()))
                .forEach(this::deleteRoute);

        if (interfaceManager != null) {
            interfaceManager.cleanup();
        }
    }

    private Router createRouter(RouterInfo info) {
        return new Router(
                info,
                interfaceService,
                deviceService,
                this::provisionInterface,
                this::unprovisionInterface,
                false);
    }

    private void updateRoute(ResolvedRoute route) {
        addNextHop(route);

        Integer nextId;
        synchronized (this) {
            nextId = nextHops.get(route.nextHop());
        }

        flowObjectiveService.forward(deviceId,
                generateRibForwardingObj(route.prefix(), nextId).add());
        log.trace("Sending forwarding objective {} -> nextId:{}", route, nextId);
    }

    private synchronized void deleteRoute(ResolvedRoute route) {
        deleteRoute(new Route(Route.Source.UNDEFINED, route.prefix(), route.nextHop()));
    }

    private void deleteRoute(Route route) {
        //Integer nextId = nextHops.get(route.nextHop());

        /* Group group = deleteNextHop(route.prefix());
        if (group == null) {
            log.warn("Group not found when deleting {}", route);
            return;
        }*/

        flowObjectiveService.forward(deviceId,
                generateRibForwardingObj(route.prefix(), null).remove());
    }

    private ForwardingObjective.Builder generateRibForwardingObj(IpPrefix prefix,
                                                                 Integer nextId) {
        TrafficSelector selector = buildIpSelectorFromIpPrefix(prefix).build();
        int priority = prefix.prefixLength() * PRIORITY_MULTIPLIER + PRIORITY_OFFSET;

        ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective.builder()
                .fromApp(fibAppId)
                .makePermanent()
                .withSelector(selector)
                .withPriority(priority)
                .withFlag(ForwardingObjective.Flag.SPECIFIC);

        if (nextId == null) {
            // Route withdraws are not specified with next hops. Generating
            // dummy treatment as there is no equivalent nextId info.
            fwdBuilder.withTreatment(DefaultTrafficTreatment.builder().build());
        } else {
            fwdBuilder.nextStep(nextId);
        }
        return fwdBuilder;
    }

    /**
     * Method to build IPv4 or IPv6 selector.
     *
     * @param prefixToMatch the prefix to match
     * @return the traffic selector builder
     */
    private TrafficSelector.Builder buildIpSelectorFromIpPrefix(IpPrefix prefixToMatch) {
        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
        // If the prefix is IPv4
        if (prefixToMatch.isIp4()) {
            selectorBuilder.matchEthType(Ethernet.TYPE_IPV4);
            selectorBuilder.matchIPDst(prefixToMatch);
            return selectorBuilder;
        }
        // If the prefix is IPv6
        selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
        selectorBuilder.matchIPv6Dst(prefixToMatch);
        return selectorBuilder;
    }

    private synchronized void addNextHop(ResolvedRoute route) {
        prefixToNextHop.put(route.prefix(), route.nextHop());
        if (nextHopsCount.count(route.nextHop()) == 0) {
            // There was no next hop in the multiset
            Interface egressIntf = interfaceService.getMatchingInterface(route.nextHop());
            if (egressIntf == null) {
                log.warn("no egress interface found for {}", route);
                return;
            }

            NextHopGroupKey groupKey = new NextHopGroupKey(route.nextHop());

            NextHop nextHop = new NextHop(route.nextHop(), route.nextHopMac(), groupKey);

            TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder()
                    .setEthSrc(egressIntf.mac())
                    .setEthDst(nextHop.mac());

            TrafficSelector.Builder metabuilder = null;
            if (!egressIntf.vlan().equals(VlanId.NONE)) {
                treatment.pushVlan()
                        .setVlanId(egressIntf.vlan())
                        .setVlanPcp((byte) 0);
            } else {
                // untagged outgoing port may require internal vlan in some pipelines
                metabuilder = DefaultTrafficSelector.builder();
                metabuilder.matchVlanId(VlanId.vlanId(ASSIGNED_VLAN));
            }

            treatment.setOutput(egressIntf.connectPoint().port());

            int nextId = flowObjectiveService.allocateNextId();
            NextObjective.Builder nextBuilder = DefaultNextObjective.builder()
                    .withId(nextId)
                    .addTreatment(treatment.build())
                    .withType(NextObjective.Type.SIMPLE)
                    .fromApp(fibAppId);
            if (metabuilder != null) {
                nextBuilder.withMeta(metabuilder.build());
            }

            NextObjective nextObjective = nextBuilder.add(); // TODO add callbacks
            flowObjectiveService.next(deviceId, nextObjective);

            nextHops.put(nextHop.ip(), nextId);

            if (routeToNextHop) {
                // Install route to next hop
                ForwardingObjective fob =
                        generateRibForwardingObj(IpPrefix.valueOf(route.nextHop(), 32), nextId).add();
                flowObjectiveService.forward(deviceId, fob);
            }
        }

        nextHopsCount.add(route.nextHop());
    }

    /*private synchronized Group deleteNextHop(IpPrefix prefix) {
        IpAddress nextHopIp = prefixToNextHop.remove(prefix);
        NextHop nextHop = nextHops.get(nextHopIp);
        if (nextHop == null) {
            log.warn("No next hop found when removing prefix {}", prefix);
            return null;
        }

        Group group = groupService.getGroup(deviceId,
                                            new DefaultGroupKey(appKryo.
                                                                serialize(nextHop.group())));

        // FIXME disabling group deletes for now until we verify the logic is OK
        if (nextHopsCount.remove(nextHopIp, 1) <= 1) {
            // There was one or less next hops, so there are now none

            log.debug("removing group for next hop {}", nextHop);

            nextHops.remove(nextHopIp);

            groupService.removeGroup(deviceId,
                                     new DefaultGroupKey(appKryo.build().serialize(nextHop.group())),
                                     appId);
        }

        return group;
    }*/

    private void provisionInterface(InterfaceProvisionRequest intf) {
        updateInterfaceFilters(intf, true);
    }

    private void unprovisionInterface(InterfaceProvisionRequest intf) {
        updateInterfaceFilters(intf, false);
    }

    /**
     * Installs or removes flow objectives relating to an interface.
     *
     * @param intf interface to update objectives for
     * @param install true to install the objectives, false to remove them
     */
    private void updateInterfaceFilters(InterfaceProvisionRequest intf, boolean install) {
        updateFilteringObjective(intf, install);
        updateMcastFilteringObjective(intf, install);
    }

    /**
     * Installs or removes unicast filtering objectives relating to an interface.
     *
     * @param routerIntf interface to update objectives for
     * @param install true to install the objectives, false to remove them
     */
    private void updateFilteringObjective(InterfaceProvisionRequest routerIntf, boolean install) {
        Interface intf = routerIntf.intf();
        VlanId assignedVlan = (egressVlan().equals(VlanId.NONE)) ?
                VlanId.vlanId(ASSIGNED_VLAN) :
                egressVlan();

        FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
        // first add filter for the interface
        fob.withKey(Criteria.matchInPort(intf.connectPoint().port()))
            .addCondition(Criteria.matchEthDst(intf.mac()))
            .addCondition(Criteria.matchVlanId(intf.vlan()));
        fob.withPriority(PRIORITY_OFFSET);
        if (intf.vlan() == VlanId.NONE) {
            TrafficTreatment tt = DefaultTrafficTreatment.builder()
                    .pushVlan().setVlanId(assignedVlan).build();
            fob.withMeta(tt);
        }
        fob.permit().fromApp(fibAppId);
        sendFilteringObjective(install, fob, intf);

        // then add the same mac/vlan filters for control-plane connect point
        fob.withKey(Criteria.matchInPort(routerIntf.controlPlaneConnectPoint().port()));
        sendFilteringObjective(install, fob, intf);
    }

    /**
     * Installs or removes multicast filtering objectives relating to an interface.
     *
     * @param routerIntf interface to update objectives for
     * @param install true to install the objectives, false to remove them
     */
    private void updateMcastFilteringObjective(InterfaceProvisionRequest routerIntf, boolean install) {
        Interface intf = routerIntf.intf();
        VlanId assignedVlan = (egressVlan().equals(VlanId.NONE)) ?
                VlanId.vlanId(ASSIGNED_VLAN) :
                egressVlan();

        FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
        // first add filter for the interface
        fob.withKey(Criteria.matchInPort(intf.connectPoint().port()))
                .addCondition(Criteria.matchEthDstMasked(MacAddress.IPV4_MULTICAST,
                        MacAddress.IPV4_MULTICAST_MASK))
                .addCondition(Criteria.matchVlanId(ingressVlan()));
        fob.withPriority(PRIORITY_OFFSET);
        TrafficTreatment tt = DefaultTrafficTreatment.builder()
                .pushVlan().setVlanId(assignedVlan).build();
        fob.withMeta(tt);

        fob.permit().fromApp(fibAppId);
        sendFilteringObjective(install, fob, intf);
    }

    private void sendFilteringObjective(boolean install, FilteringObjective.Builder fob,
                                        Interface intf) {

        ObjectiveContext context = new DefaultObjectiveContext(
                (objective) -> log.info("Installed filter for interface {}", intf),
                (objective, error) ->
                        log.error("Failed to install filter for interface {}: {}", intf, error));

        FilteringObjective filter = install ? fob.add(context) : fob.remove(context);

        flowObjectiveService.filter(deviceId, filter);
    }

    private VlanId ingressVlan() {
        McastConfig mcastConfig =
                networkConfigService.getConfig(coreAppId, McastConfig.class);
        return (mcastConfig != null) ? mcastConfig.ingressVlan() : VlanId.NONE;
    }

    private VlanId egressVlan() {
        McastConfig mcastConfig =
                networkConfigService.getConfig(coreAppId, McastConfig.class);
        return (mcastConfig != null) ? mcastConfig.egressVlan() : VlanId.NONE;
    }

    /**
     * Listener for route changes.
     */
    private class InternalRouteListener implements RouteListener {
        @Override
        public void event(RouteEvent event) {
            ResolvedRoute route = event.subject();
            switch (event.type()) {
            case ROUTE_ADDED:
            case ROUTE_UPDATED:
                updateRoute(route);
                break;
            case ROUTE_REMOVED:
                deleteRoute(route);
                break;
            default:
                break;
            }
        }
    }

    /**
     * Listener for network config events.
     */
    private class InternalNetworkConfigListener implements NetworkConfigListener {
        @Override
        public void event(NetworkConfigEvent event) {
            if (event.configClass().equals(RoutingService.ROUTER_CONFIG_CLASS)) {
                switch (event.type()) {
                case CONFIG_ADDED:
                case CONFIG_UPDATED:
                    processRouterConfig();
                    break;
                case CONFIG_REGISTERED:
                    break;
                case CONFIG_UNREGISTERED:
                    break;
                case CONFIG_REMOVED:
                    cleanUp();
                    break;
                default:
                    break;
                }
            }
        }
    }
}
