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

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.Uninterruptibles;
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.core.DefaultApplication;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.core.Version;
import org.onosproject.core.VersionService;
import org.onosproject.event.AbstractListenerManager;
import org.onosproject.security.Permission;
import org.onosproject.security.SecurityUtil;
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.slf4j.Logger;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
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.*;
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 = {ApplicationService.class, ApplicationAdminService.class})
public class ApplicationManager
        extends AbstractListenerManager<ApplicationEvent, ApplicationListener>
        implements ApplicationService, ApplicationAdminService {

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

    private static final String APP_REGISTRY_URL = "http://api.onosproject.org:8080/api/applications";

    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)
    protected ApplicationStore store;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected VersionService versionService;

    // 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);
    }

    @Override
    public InputStream getApplicationArchive(ApplicationId appId) {
        checkNotNull(appId, APP_ID_NULL);
        return store.getApplicationArchive(appId);
    }

    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);
            }
        }
    }

    @Override
    public Set<Application> getRegisteredApplications() {
        ImmutableSet.Builder<Application> builder = ImmutableSet.builder();
        ObjectMapper mapper = new ObjectMapper();

        // Get input stream from the URL
        try {
            URL githubUrl = new URL(APP_REGISTRY_URL + "?onosVersion=" + versionService.version().toString());
            HttpURLConnection githubHttp = (HttpURLConnection) githubUrl.openConnection();
            InputStream githubStream = githubHttp.getInputStream();

            // Read input stream into an ArrayNode
            ArrayNode rootTree = (ArrayNode) mapper.readTree(githubStream);

            // Iterate over the array node for each object add each version as application object to the set
            rootTree.forEach(n -> {
                mapObject(builder, (ObjectNode) n);
            });

            //Iterate through Builder to remove unnecessary apps
            Set<Application> apps = builder.build();

            return apps;
        } catch (MalformedURLException e) {
            throw new IllegalStateException("Bad URL " + APP_REGISTRY_URL, e);
        } catch (IOException e) {
            throw new IllegalStateException("Unable to fetch URL " + APP_REGISTRY_URL, e);
        }
    }

    private void mapObject(ImmutableSet.Builder<Application> apps, ObjectNode node) {
        String appIDs = node.get("id").asText();
        ApplicationId appID = new DefaultApplicationId(1, appIDs);
        String title = node.get("title").asText();
        String readme = node.get("readme").asText();
        String category = node.get("category").asText();
        String url = node.get("url").asText();
        String origin = node.get("maintainer").asText();
        JsonNode it = node.get("versions");
        Iterator iterate = it.iterator();
        while (iterate.hasNext()) {
            DefaultApplication.Builder app = new DefaultApplication.Builder();
            JsonNode jsonNode = (JsonNode) iterate.next();
            URL imageUrl = null;
            try {
                imageUrl = new URL(jsonNode.get("oarURL").asText());
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
            Version version1 = Version.version(jsonNode.get("onosVersion").asText());
            app.withImageUrl(imageUrl)
                    .withAppId(new DefaultApplicationId(1, node.get("id").asText()))
                    .withVersion(version1)
                    .withAppId(appID)
                    .withReadme(readme)
                    .withDescription(readme)
                    .withTitle(title)
                    .withFeatures(ImmutableList.of("none"))
                    .withCategory(category)
                    .withUrl(url)
                    .withOrigin(origin);
            apps.add(app.build());
        }
    }
}