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

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.apache.commons.lang3.tuple.Pair;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.protection.ProtectedTransportEndpointDescription;
import org.onosproject.net.behaviour.protection.ProtectionConfig;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.intent.IntentData;
import org.onosproject.net.intent.IntentException;
import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.IntentInstallCoordinator;
import org.onosproject.net.intent.IntentOperationContext;
import org.onosproject.net.intent.IntentInstaller;
import org.onosproject.net.intent.ProtectionEndpointIntent;
import org.onosproject.net.intent.impl.IntentManager;
import org.onosproject.net.intent.ObjectiveTrackerService;
import org.slf4j.Logger;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.net.config.NetworkConfigEvent.Type.*;
import static org.onosproject.net.intent.IntentInstaller.Direction.ADD;
import static org.onosproject.net.intent.IntentInstaller.Direction.REMOVE;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Installer for ProtectionEndpointIntent.
 */
@Component(immediate = true)
public class ProtectionEndpointIntentInstaller implements IntentInstaller<ProtectionEndpointIntent> {
    private static final String CONFIG_FAILED = "Config operation unsuccessful, expected %s, actual %s.";
    private final Logger log = getLogger(IntentManager.class);

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected IntentExtensionService intentExtensionService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    NetworkConfigService networkConfigService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    IntentInstallCoordinator intentInstallCoordinator;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    ObjectiveTrackerService trackerService;

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

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

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

        List<ProtectionEndpointIntent> uninstallIntents = context.intentsToUninstall();
        List<ProtectionEndpointIntent> installIntents = context.intentsToInstall();

        if (!toInstall.isPresent() && !toUninstall.isPresent()) {
            intentInstallCoordinator.intentInstallSuccess(context);
            return;
        }

        if (toUninstall.isPresent()) {
            IntentData intentData = toUninstall.get();
            trackerService.removeTrackedResources(intentData.key(), intentData.intent().resources());
            uninstallIntents.forEach(installable ->
                                             trackerService.removeTrackedResources(intentData.intent().key(),
                                                                                   installable.resources()));
        }

        if (toInstall.isPresent()) {
            IntentData intentData = toInstall.get();
            trackerService.addTrackedResources(intentData.key(), intentData.intent().resources());
            installIntents.forEach(installable ->
                                           trackerService.addTrackedResources(intentData.key(),
                                                                              installable.resources()));
        }

        List<Stage> stages = new ArrayList<>();

        stages.add(new Stage(uninstallIntents.stream()
                                     .map(i -> Pair.of(i, REMOVE))
                                     .collect(Collectors.toList())));

        stages.add(new Stage(installIntents.stream()
                                     .map(i -> Pair.of(i, ADD))
                                     .collect(Collectors.toList())));
        for (Stage stage : stages) {
            log.debug("applying Stage {}", stage);
            try {
                // wait for stage completion
                stage.apply();
                stage.listeners().forEach(networkConfigService::removeListener);
            } catch (IntentException e) {
                log.error("Stage {} failed, reason: {}", stage, e.toString());
                intentInstallCoordinator.intentInstallFailed(context);
                return;
            }
        }
        // All stage success
        intentInstallCoordinator.intentInstallSuccess(context);
    }

    /**
     * Stage of installable Intents which can be processed in parallel.
     */
    private final class Stage {
        // should it have progress state, how far it went?
        private final Collection<Pair<ProtectionEndpointIntent, Direction>> ops;
        private final Set<NetworkConfigListener> listeners = Sets.newHashSet();

        /**
         * Create a stage with given operations.
         *
         * @param ops the operations
         */
        Stage(Collection<Pair<ProtectionEndpointIntent, Direction>> ops) {
            this.ops = checkNotNull(ops);
        }

        /**
         * Applies all operations for this stage.
         *
         * @return the CompletableFuture object for this operation
         */
        void apply() {
            ops.stream()
                    .map(op -> applyOp(op.getRight(), op.getLeft()))
                    .forEach(future -> {
                        try {
                            future.get(100, TimeUnit.MILLISECONDS);
                        } catch (TimeoutException | InterruptedException | ExecutionException e) {
                            throw new IntentException(e.toString());
                        }
                    });
        }

        /**
         * Applies the protection endpoint Intent with a given direction.
         *
         * @param dir the direction
         * @param intent the protection endpoint Intent
         * @return the CompletableFuture object for this operation
         */
        private CompletableFuture<Void> applyOp(Direction dir, ProtectionEndpointIntent intent) {
            log.trace("applying {}: {}", dir, intent);
            if (dir == REMOVE) {
                ProtectionConfigListener listener =
                        new ProtectionConfigListener(ImmutableSet.of(CONFIG_REMOVED),
                                                     intent.deviceId());
                networkConfigService.addListener(listener);
                listeners.add(listener);
                networkConfigService.removeConfig(intent.deviceId(), ProtectionConfig.class);
                return listener.completableFuture();
            } else {
                ProtectedTransportEndpointDescription description = intent.description();

                // Can't do following. Will trigger empty CONFIG_ADDED
                //ProtectionConfig cfg = networkConfigService.addConfig(intent.deviceId(),
                //                                                      ProtectionConfig.class);
                ProtectionConfig cfg = new ProtectionConfig(intent.deviceId());
                cfg.fingerprint(description.fingerprint());
                cfg.peer(description.peer());
                cfg.paths(description.paths());
                ProtectionConfigListener listener =
                        new ProtectionConfigListener(ImmutableSet.of(CONFIG_ADDED, CONFIG_UPDATED),
                                                     intent.deviceId());

                networkConfigService.addListener(listener);
                listeners.add(listener);
                networkConfigService.applyConfig(intent.deviceId(),
                                                 ProtectionConfig.class,
                                                 cfg.node());
                return listener.completableFuture();
            }
        }

        @Override
        public String toString() {
            return ops.toString();
        }

        public Set<NetworkConfigListener> listeners() {
            return listeners;
        }

        /**
         * Listener for protection config for specific config event and device.
         */
        class ProtectionConfigListener implements NetworkConfigListener {
            private CompletableFuture<Void> completableFuture;
            private Set<NetworkConfigEvent.Type> listenTypes;
            private DeviceId listenDevice;

            public ProtectionConfigListener(Set<NetworkConfigEvent.Type> listenTypes, DeviceId listenDevice) {
                completableFuture = new CompletableFuture<>();
                this.listenTypes = listenTypes;
                this.listenDevice = listenDevice;
            }

            @Override
            public void event(NetworkConfigEvent event) {
                if (!event.subject().equals(listenDevice)) {
                    return;
                }
                if (!listenTypes.contains(event.type())) {
                    String errorMsg = String.format(CONFIG_FAILED, listenTypes.toString(), event.type());
                    completableFuture.completeExceptionally(new IntentException(errorMsg));
                } else {
                    completableFuture.complete(null);
                }
            }

            public CompletableFuture<Void> completableFuture() {
                return completableFuture;
            }
        }
    }
}
