/*
 * Copyright 2015-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.app.impl;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.Uninterruptibles;

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.apache.felix.scr.annotations.Service;
import org.apache.karaf.features.Feature;
import org.apache.karaf.features.FeaturesService;
import org.onosproject.app.ApplicationAdminService;
import org.onosproject.app.ApplicationEvent;
import org.onosproject.app.ApplicationListener;
import org.onosproject.app.ApplicationService;
import org.onosproject.app.ApplicationState;
import org.onosproject.app.ApplicationStore;
import org.onosproject.app.ApplicationStoreDelegate;
import org.onosproject.core.Application;
import org.onosproject.core.ApplicationId;
import org.onosproject.event.AbstractListenerManager;
import org.onosproject.security.Permission;
import org.onosproject.security.SecurityUtil;
import org.slf4j.Logger;

import java.io.InputStream;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.app.ApplicationEvent.Type.APP_ACTIVATED;
import static org.onosproject.app.ApplicationEvent.Type.APP_DEACTIVATED;
import static org.onosproject.app.ApplicationEvent.Type.APP_INSTALLED;
import static org.onosproject.app.ApplicationEvent.Type.APP_UNINSTALLED;
import static org.onosproject.security.AppGuard.checkPermission;
import static org.onosproject.security.AppPermission.Type.APP_READ;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Implementation of the application management service.
 */
@Component(immediate = true)
@Service
public class ApplicationManager
        extends AbstractListenerManager<ApplicationEvent, ApplicationListener>
        implements ApplicationService, ApplicationAdminService {

    private final Logger log = getLogger(getClass());

    private static final String APP_ID_NULL = "Application ID cannot be null";
    private static final long DEFAULT_OPERATION_TIMEOUT_MILLIS = 2000;

    private final ApplicationStoreDelegate delegate = new InternalStoreDelegate();

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ApplicationStore store;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected FeaturesService featuresService;

    // Application supplied hooks for pre-activation processing.
    private final Multimap<String, Runnable> deactivateHooks = HashMultimap.create();
    private final Cache<ApplicationId, CountDownLatch> pendingOperations =
            CacheBuilder.newBuilder()
                        .expireAfterWrite(DEFAULT_OPERATION_TIMEOUT_MILLIS * 2, TimeUnit.MILLISECONDS)
                        .build();

    @Activate
    public void activate() {
        eventDispatcher.addSink(ApplicationEvent.class, listenerRegistry);
        store.setDelegate(delegate);
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        eventDispatcher.removeSink(ApplicationEvent.class);
        store.unsetDelegate(delegate);
        log.info("Stopped");
    }

    @Override
    public Set<Application> getApplications() {
        checkPermission(APP_READ);
        return store.getApplications();
    }

    @Override
    public ApplicationId getId(String name) {
        checkPermission(APP_READ);
        checkNotNull(name, "Name cannot be null");
        return store.getId(name);
    }

    @Override
    public Application getApplication(ApplicationId appId) {
        checkPermission(APP_READ);
        checkNotNull(appId, APP_ID_NULL);
        return store.getApplication(appId);
    }

    @Override
    public ApplicationState getState(ApplicationId appId) {
        checkPermission(APP_READ);
        checkNotNull(appId, APP_ID_NULL);
        return store.getState(appId);
    }

    @Override
    public Set<Permission> getPermissions(ApplicationId appId) {
        checkPermission(APP_READ);
        checkNotNull(appId, APP_ID_NULL);
        return store.getPermissions(appId);
    }

    @Override
    public void registerDeactivateHook(ApplicationId appId, Runnable hook) {
        checkPermission(APP_READ);
        checkNotNull(appId, APP_ID_NULL);
        checkNotNull(hook, "Hook cannot be null");
        deactivateHooks.put(appId.name(), hook);
    }

    @Override
    public Application install(InputStream appDescStream) {
        checkNotNull(appDescStream, "Application archive stream cannot be null");
        Application app = store.create(appDescStream);
        SecurityUtil.register(app.id());
        return app;
    }

    @Override
    public void uninstall(ApplicationId appId) {
        checkNotNull(appId, APP_ID_NULL);
        updateStoreAndWaitForNotificationHandling(appId, store::remove);
    }

    @Override
    public void activate(ApplicationId appId) {
        checkNotNull(appId, APP_ID_NULL);
        if (!SecurityUtil.isAppSecured(appId)) {
            return;
        }
        updateStoreAndWaitForNotificationHandling(appId, store::activate);
    }

    @Override
    public void deactivate(ApplicationId appId) {
        checkNotNull(appId, APP_ID_NULL);
        updateStoreAndWaitForNotificationHandling(appId, store::deactivate);
    }

    @Override
    public void setPermissions(ApplicationId appId, Set<Permission> permissions) {
        checkNotNull(appId, APP_ID_NULL);
        checkNotNull(permissions, "Permissions cannot be null");
        store.setPermissions(appId, permissions);
    }

    private void updateStoreAndWaitForNotificationHandling(ApplicationId appId,
                                                           Consumer<ApplicationId> storeUpdateTask) {
        CountDownLatch latch = new CountDownLatch(1);
        try {
            pendingOperations.put(appId, latch);
            storeUpdateTask.accept(appId);
        } catch (Exception e) {
            pendingOperations.invalidate(appId);
            latch.countDown();
            log.warn("Failed to update store for {}", appId.name(), e);
        }
        Uninterruptibles.awaitUninterruptibly(latch, DEFAULT_OPERATION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
    }

    private class InternalStoreDelegate implements ApplicationStoreDelegate {
        @Override
        public void notify(ApplicationEvent event) {
            ApplicationEvent.Type type = event.type();
            Application app = event.subject();
            CountDownLatch latch = pendingOperations.getIfPresent(app.id());
            try {
                if (type == APP_ACTIVATED) {
                    if (installAppFeatures(app)) {
                        log.info("Application {} has been activated", app.id().name());
                    }

                } else if (type == APP_DEACTIVATED) {
                    if (uninstallAppFeatures(app)) {
                        log.info("Application {} has been deactivated", app.id().name());
                    }

                } else if (type == APP_INSTALLED) {
                    if (installAppArtifacts(app)) {
                        log.info("Application {} has been installed", app.id().name());
                    }

                } else if (type == APP_UNINSTALLED) {
                    if (uninstallAppFeatures(app) || uninstallAppArtifacts(app)) {
                        log.info("Application {} has been uninstalled", app.id().name());
                    }

                }
                post(event);
            } catch (Exception e) {
                log.warn("Unable to perform operation on application " + app.id().name(), e);
            } finally {
                if (latch != null) {
                    latch.countDown();
                    pendingOperations.invalidate(app.id());
                }
            }
        }
    }

    // The following methods are fully synchronized to guard against remote vs.
    // locally induced feature service interactions.

    // Installs all feature repositories required by the specified app.
    private synchronized boolean installAppArtifacts(Application app) throws Exception {
        if (app.featuresRepo().isPresent() &&
                featuresService.getRepository(app.featuresRepo().get()) == null) {
            featuresService.addRepository(app.featuresRepo().get());
            return true;
        }
        return false;
    }

    // Uninstalls all the feature repositories required by the specified app.
    private synchronized boolean uninstallAppArtifacts(Application app) throws Exception {
        if (app.featuresRepo().isPresent() &&
                featuresService.getRepository(app.featuresRepo().get()) != null) {
            featuresService.removeRepository(app.featuresRepo().get());
            return true;
        }
        return false;
    }

    // Installs all features that define the specified app.
    private synchronized boolean installAppFeatures(Application app) throws Exception {
        boolean changed = false;
        for (String name : app.features()) {
            Feature feature = featuresService.getFeature(name);

            // If we see an attempt at activation of a non-existent feature
            // attempt to install the app artifacts first and then retry.
            // This can be triggered by a race condition between different ONOS
            // instances "installing" the apps from disk at their own pace.
            // Perhaps there is a more elegant solution to be explored in the
            // future.
            if (feature == null) {
                installAppArtifacts(app);
                feature = featuresService.getFeature(name);
            }

            if (feature != null && !featuresService.isInstalled(feature)) {
                featuresService.installFeature(name);
                changed = true;
            } else if (feature == null) {
                log.warn("Feature {} not found", name);
            }
        }
        return changed;
    }

    // Uninstalls all features that define the specified app.
    private synchronized boolean uninstallAppFeatures(Application app) throws Exception {
        boolean changed = false;
        deactivateHooks.removeAll(app.id().name()).forEach(hook -> invokeHook(hook, app.id()));
        for (String name : app.features()) {
            Feature feature = featuresService.getFeature(name);
            if (feature != null && featuresService.isInstalled(feature)) {
                featuresService.uninstallFeature(name);
                changed = true;
            } else if (feature == null) {
                log.warn("Feature {} not found", name);
            }
        }
        return changed;
    }

    // Invokes the specified function, if not null.
    @java.lang.SuppressWarnings("squid:S1217") // We really do mean to call run()
    private void invokeHook(Runnable hook, ApplicationId appId) {
        if (hook != null) {
            try {
                hook.run();
            } catch (Exception e) {
                log.warn("Deactivate hook for application {} encountered an error",
                         appId.name(), e);
            }
        }
    }

}
