/*
 * 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.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flowobjective.DefaultFilteringObjective;
import org.onosproject.net.flowobjective.DefaultObjectiveContext;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.ObjectiveContext;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashSet;
import java.util.Set;

/**
 * Handles Segment Routing app config events.
 */
public class AppConfigHandler {
    private static final Logger log = LoggerFactory.getLogger(AppConfigHandler.class);
    private final SegmentRoutingManager srManager;
    private final DeviceService deviceService;

    /**
     * Constructs Segment Routing App Config Handler.
     *
     * @param srManager instance of {@link SegmentRoutingManager}
     */
    public AppConfigHandler(SegmentRoutingManager srManager) {
        this.srManager = srManager;
        this.deviceService = srManager.deviceService;
    }

    /**
     * Processes Segment Routing App Config added event.
     *
     * @param event network config added event
     */
    protected void processAppConfigAdded(NetworkConfigEvent event) {
        log.info("Processing AppConfig CONFIG_ADDED");
        SegmentRoutingAppConfig config = (SegmentRoutingAppConfig) event.config().get();
        deviceService.getAvailableDevices().forEach(device -> {
            populateVRouter(device.id(), getMacAddresses(config));
            config.blackholeIPs().forEach(ipPrefix -> {
                srManager.routingRulePopulator.populateDefaultRouteBlackhole(device.id(), ipPrefix);
            });
        });
    }

    /**
     * Processes Segment Routing App Config updated event.
     *
     * @param event network config updated event
     */
    protected void processAppConfigUpdated(NetworkConfigEvent event) {
        log.info("Processing AppConfig CONFIG_UPDATED");
        SegmentRoutingAppConfig config = (SegmentRoutingAppConfig) event.config().get();
        SegmentRoutingAppConfig prevConfig = (SegmentRoutingAppConfig) event.prevConfig().get();
        deviceService.getAvailableDevices().forEach(device -> {
            Set<MacAddress> macAddresses = new HashSet<>(getMacAddresses(config));
            Set<MacAddress> prevMacAddresses = new HashSet<>(getMacAddresses(prevConfig));
            // Avoid removing and re-adding unchanged MAC addresses since
            // FlowObjective does not guarantee the execution order.
            Set<MacAddress> sameMacAddresses = new HashSet<>(macAddresses);
            sameMacAddresses.retainAll(prevMacAddresses);
            macAddresses.removeAll(sameMacAddresses);
            prevMacAddresses.removeAll(sameMacAddresses);

            revokeVRouter(device.id(), prevMacAddresses);
            populateVRouter(device.id(), macAddresses);
            Set<IpPrefix> toRemove = Sets.difference(prevConfig.blackholeIPs(), config.blackholeIPs());
            toRemove.forEach(ipPrefix -> {
                srManager.routingRulePopulator.removeDefaultRouteBlackhole(device.id(), ipPrefix);
            });
            Set<IpPrefix> toAdd = Sets.difference(config.blackholeIPs(), prevConfig.blackholeIPs());
            toAdd.forEach(ipPrefix -> {
                srManager.routingRulePopulator.populateDefaultRouteBlackhole(device.id(), ipPrefix);
            });
        });

    }

    /**
     * Processes Segment Routing App Config removed event.
     *
     * @param event network config removed event
     */
    protected void processAppConfigRemoved(NetworkConfigEvent event) {
        log.info("Processing AppConfig CONFIG_REMOVED");
        SegmentRoutingAppConfig prevConfig = (SegmentRoutingAppConfig) event.prevConfig().get();
        deviceService.getAvailableDevices().forEach(device -> {
            revokeVRouter(device.id(), getMacAddresses(prevConfig));
            prevConfig.blackholeIPs().forEach(ipPrefix -> {
                srManager.routingRulePopulator.removeDefaultRouteBlackhole(device.id(), ipPrefix);
            });
        });
    }

    /**
     * Populates initial vRouter and blackhole rules.
     *
     * @param deviceId device ID
     */
    public void init(DeviceId deviceId) {
        SegmentRoutingAppConfig config =
                srManager.cfgService.getConfig(srManager.appId, SegmentRoutingAppConfig.class);
        populateVRouter(deviceId, getMacAddresses(config));
        if (config != null) {
            config.blackholeIPs().forEach(ipPrefix -> {
                srManager.routingRulePopulator.populateDefaultRouteBlackhole(deviceId, ipPrefix);
            });
        }
    }

    private void populateVRouter(DeviceId deviceId, Set<MacAddress> pendingAdd) {
        if (!isEdge(deviceId)) {
            return;
        }
        getVRouterFlowObjBuilders(pendingAdd).forEach(foBuilder -> {
            ObjectiveContext context = new DefaultObjectiveContext(
                    (objective) -> log.debug("vRouterMac filter for {} populated", pendingAdd),
                    (objective, error) ->
                            log.warn("Failed to populate vRouterMac filter for {}: {}", pendingAdd, error));
            srManager.flowObjectiveService.filter(deviceId, foBuilder.add(context));
        });
    }

    private void revokeVRouter(DeviceId deviceId, Set<MacAddress> pendingRemove) {
        if (!isEdge(deviceId)) {
            return;
        }
        getVRouterFlowObjBuilders(pendingRemove).forEach(foBuilder -> {
            ObjectiveContext context = new DefaultObjectiveContext(
                    (objective) -> log.debug("vRouterMac filter for {} revoked", pendingRemove),
                    (objective, error) ->
                            log.warn("Failed to revoke vRouterMac filter for {}: {}", pendingRemove, error));
            srManager.flowObjectiveService.filter(deviceId, foBuilder.remove(context));
        });
    }

    private Set<FilteringObjective.Builder> getVRouterFlowObjBuilders(Set<MacAddress> macAddresses) {
        ImmutableSet.Builder<FilteringObjective.Builder> setBuilder = ImmutableSet.builder();
        macAddresses.forEach(macAddress -> {
            FilteringObjective.Builder fobuilder = DefaultFilteringObjective.builder();
            fobuilder.withKey(Criteria.matchInPort(PortNumber.ANY))
                    .addCondition(Criteria.matchEthDst(macAddress))
                    .permit()
                    .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
                    .fromApp(srManager.appId);
            setBuilder.add(fobuilder);
        });
        return setBuilder.build();
    }

    private Set<MacAddress> getMacAddresses(SegmentRoutingAppConfig config) {
        if (config == null) {
            return ImmutableSet.of();
        }
        return ImmutableSet.copyOf(config.vRouterMacs());
    }

    private boolean isEdge(DeviceId deviceId) {
        try {
            if (srManager.deviceConfiguration.isEdgeDevice(deviceId)) {
                return true;
            }
        } catch (DeviceConfigNotFoundException e) {
            log.warn("Device configuration for {} is not present.", deviceId);
        }
        return false;
    }
}
