/*
 * 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.net.intent.impl.installer;

import com.google.common.collect.Lists;
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.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleOperations;
import org.onosproject.net.flow.FlowRuleOperationsContext;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.intent.FlowRuleIntent;
import org.onosproject.net.intent.IntentInstallCoordinator;
import org.onosproject.net.intent.IntentData;
import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.IntentOperationContext;
import org.onosproject.net.intent.IntentInstaller;
import org.onosproject.net.intent.impl.IntentManager;
import org.onosproject.net.intent.impl.ObjectiveTrackerService;
import org.slf4j.Logger;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import static org.onosproject.net.intent.IntentInstaller.Direction.ADD;
import static org.onosproject.net.intent.IntentInstaller.Direction.REMOVE;
import static org.onosproject.net.intent.IntentState.INSTALLED;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Installer for FlowRuleIntent.
 */
@Component(immediate = true)
public class FlowRuleIntentInstaller implements IntentInstaller<FlowRuleIntent> {
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected IntentExtensionService intentExtensionService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ObjectiveTrackerService trackerService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected IntentInstallCoordinator intentInstallCoordinator;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected FlowRuleService flowRuleService;

    @Activate
    public void activate() {
        intentExtensionService.registerInstaller(FlowRuleIntent.class, this);
    }

    @Deactivate
    public void deactivated() {
        intentExtensionService.unregisterInstaller(FlowRuleIntent.class);
    }

    protected final Logger log = getLogger(IntentManager.class);

    @Override
    public void apply(IntentOperationContext<FlowRuleIntent> context) {
        Optional<IntentData> toUninstall = context.toUninstall();
        Optional<IntentData> toInstall = context.toInstall();

        List<FlowRuleIntent> uninstallIntents = Lists.newArrayList(context.intentsToUninstall());
        List<FlowRuleIntent> installIntents = Lists.newArrayList(context.intentsToInstall());

        if (!toInstall.isPresent() && !toUninstall.isPresent()) {
            intentInstallCoordinator.intentInstallSuccess(context);
            return;
        } else if (!toInstall.isPresent()) {
            // Uninstall only
            trackIntentResources(toUninstall.get(), uninstallIntents, REMOVE);
        } else if (!toUninstall.isPresent()) {
            // Install only
            trackIntentResources(toInstall.get(), installIntents, ADD);
        } else {
            IntentData uninstall = toUninstall.get();
            IntentData install = toInstall.get();
            // Filter out same intents and intents with same flow rules
            Iterator<FlowRuleIntent> iterator = installIntents.iterator();
            while (iterator.hasNext()) {
                FlowRuleIntent installIntent = iterator.next();
                uninstallIntents.stream().filter(uIntent -> {
                    if (uIntent.equals(installIntent)) {
                        return true;
                    } else {
                        return !flowRuleIntentChanged(uIntent, installIntent);
                    }
                }).findFirst().ifPresent(common -> {
                    uninstallIntents.remove(common);
                    if (INSTALLED.equals(uninstall.state())) {
                        // only remove the install intent if the existing
                        // intent (i.e. the uninstall one) is already
                        // installed or installing
                        iterator.remove();
                    }
                });
            }
            trackIntentResources(uninstall, uninstallIntents, REMOVE);
            trackIntentResources(install, installIntents, ADD);
        }

        FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
        builder.newStage();

        toUninstall.ifPresent(intentData -> {
            uninstallIntents.stream().map(FlowRuleIntent::flowRules)
                    .flatMap(Collection::stream).forEach(builder::remove);
        });

        toInstall.ifPresent(intentData -> {
            installIntents.stream().map(FlowRuleIntent::flowRules)
                    .flatMap(Collection::stream).forEach(builder::add);
        });

        FlowRuleOperationsContext flowRuleOperationsContext = new FlowRuleOperationsContext() {
            @Override
            public void onSuccess(FlowRuleOperations ops) {
                intentInstallCoordinator.intentInstallSuccess(context);
            }

            @Override
            public void onError(FlowRuleOperations ops) {
                intentInstallCoordinator.intentInstallFailed(context);
            }
        };

        FlowRuleOperations operations = builder.build(flowRuleOperationsContext);
        log.debug("applying intent {} -> {} with {} rules: {}",
                  toUninstall.map(x -> x.key().toString()).orElse("<empty>"),
                  toInstall.map(x -> x.key().toString()).orElse("<empty>"),
                  operations.stages().stream().mapToLong(Set::size).sum(),
                  operations.stages());
        flowRuleService.apply(operations);
    }

    /**
     * Track or un-track network resource of a Intent and it's installable
     * Intents.
     *
     * @param intentData the Intent data
     * @param intentsToApply the list of flow rule Intents from the Intent
     * @param direction the direction to determine track or un-track
     */
    private void trackIntentResources(IntentData intentData, List<FlowRuleIntent> intentsToApply, Direction direction) {
        switch (direction) {
            case ADD:
                trackerService.addTrackedResources(intentData.key(), intentData.intent().resources());
                intentsToApply.forEach(installable ->
                                               trackerService.addTrackedResources(intentData.key(),
                                                                                  installable.resources()));
                break;
            default:
                trackerService.removeTrackedResources(intentData.key(), intentData.intent().resources());
                intentsToApply.forEach(installable ->
                                               trackerService.removeTrackedResources(intentData.intent().key(),
                                                                                     installable.resources()));
                break;
        }
    }

    /**
     * Determines whether there is any flow rule changed
     * (i.e., different set of flow rules or different treatments)
     * between FlowRuleIntents to be uninstalled and to be installed.
     *
     * @param uninstallIntent FlowRuleIntent to uninstall
     * @param installIntent   FlowRuleIntent to install
     * @return true if flow rules which to be uninstalled contains all flow
     *         rules which to be installed; false otherwise
     */
    private boolean flowRuleIntentChanged(FlowRuleIntent uninstallIntent,
                                          FlowRuleIntent installIntent) {
        Collection<FlowRule> flowRulesToUninstall = uninstallIntent.flowRules();
        Collection<FlowRule> flowRulesToInstall = installIntent.flowRules();

        // Check if any flow rule changed
        for (FlowRule flowRuleToInstall : flowRulesToInstall) {
            if (flowRulesToUninstall.stream().noneMatch(flowRuleToInstall::exactMatch)) {
                return true;
            }
        }
        return false;
    }

}