/*
 * 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.security.store;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;

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.BundleInfo;
import org.apache.karaf.features.Feature;
import org.apache.karaf.features.FeaturesService;

import org.onlab.util.KryoNamespace;
import org.onosproject.app.ApplicationAdminService;
import org.onosproject.core.Application;
import org.onosproject.core.ApplicationId;
import org.onosproject.security.Permission;
import org.onosproject.store.AbstractStore;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.ConsistentMap;
import org.onosproject.store.service.EventuallyConsistentMap;
import org.onosproject.store.service.LogicalClockService;
import org.onosproject.store.service.MapEvent;
import org.onosproject.store.service.MapEventListener;
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.StorageService;
import org.slf4j.Logger;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

import static org.onosproject.security.store.SecurityModeState.*;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Manages application permissions granted/requested to applications.
 * Uses both gossip-based and RAFT-based distributed data store.
 */
@Component(immediate = true)
@Service
public class DistributedSecurityModeStore
        extends AbstractStore<SecurityModeEvent, SecurityModeStoreDelegate>
        implements SecurityModeStore {

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

    private ConsistentMap<ApplicationId, SecurityInfo> states;
    private EventuallyConsistentMap<ApplicationId, Set<Permission>> violations;

    private ConcurrentHashMap<String, Set<ApplicationId>> localBundleAppDirectory;
    private ConcurrentHashMap<ApplicationId, Set<String>> localAppBundleDirectory;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected StorageService storageService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected LogicalClockService clockService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ApplicationAdminService applicationAdminService;

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

    private static final Serializer STATE_SERIALIZER = Serializer.using(new KryoNamespace.Builder()
            .register(KryoNamespaces.API)
            .register(SecurityModeState.class)
            .register(SecurityInfo.class)
            .register(Permission.class)
            .build());

    private static final KryoNamespace.Builder VIOLATION_SERIALIZER = KryoNamespace.newBuilder()
            .register(KryoNamespaces.API)
            .register(Permission.class);

    @Activate
    public void activate() {
        states = storageService.<ApplicationId, SecurityInfo>consistentMapBuilder()
                .withName("smonos-sdata")
                .withSerializer(STATE_SERIALIZER)
                .build();

        states.addListener(new SecurityStateListener());

        violations = storageService.<ApplicationId, Set<Permission>>eventuallyConsistentMapBuilder()
                .withName("smonos-rperms")
                .withSerializer(VIOLATION_SERIALIZER)
                .withTimestampProvider((k, v) -> clockService.getTimestamp())
                .build();

        localBundleAppDirectory = new ConcurrentHashMap<>();
        localAppBundleDirectory = new ConcurrentHashMap<>();

        log.info("Started");

    }

    @Deactivate
    public void deactivate() {
        violations.destroy();
        log.info("Stopped");
    }


    @Override
    public Set<String> getBundleLocations(ApplicationId appId) {
        Set<String> locations = localAppBundleDirectory.get(appId);
        return locations != null ? locations : Sets.newHashSet();
    }

    @Override
    public Set<ApplicationId> getApplicationIds(String location) {
        Set<ApplicationId> appIds = localBundleAppDirectory.get(location);
        return appIds != null ? appIds : Sets.newHashSet();
    }

    @Override
    public Set<Permission> getRequestedPermissions(ApplicationId appId) {
        Set<Permission> permissions = violations.get(appId);
        return permissions != null ? permissions : ImmutableSet.of();
    }

    @Override
    public Set<Permission> getGrantedPermissions(ApplicationId appId) {
        return states.asJavaMap().getOrDefault(appId, new SecurityInfo(ImmutableSet.of(), null)).getPermissions();
    }

    @Override
    public void requestPermission(ApplicationId appId, Permission permission) {

        states.computeIf(appId, securityInfo -> (securityInfo == null || securityInfo.getState() != POLICY_VIOLATED),
                (id, securityInfo) -> new SecurityInfo(securityInfo.getPermissions(), POLICY_VIOLATED));
        violations.compute(appId, (k, v) -> v == null ? Sets.newHashSet(permission) : addAndGet(v, permission));
    }

    private Set<Permission> addAndGet(Set<Permission> oldSet, Permission newPerm) {
        oldSet.add(newPerm);
        return oldSet;
    }

    @Override
    public boolean isSecured(ApplicationId appId) {
        SecurityInfo info = states.get(appId).value();
        return info == null ? false : info.getState().equals(SECURED);
    }

    @Override
    public void reviewPolicy(ApplicationId appId) {
        Application app = applicationAdminService.getApplication(appId);
        if (app == null) {
            log.warn("Unknown Application");
            return;
        }
        states.computeIfPresent(appId, (applicationId, securityInfo) -> {
            if (securityInfo.getState().equals(INSTALLED)) {
                return new SecurityInfo(ImmutableSet.of(), REVIEWED);
            }
            return securityInfo;
        });
    }

    @Override
    public void acceptPolicy(ApplicationId appId, Set<Permission> permissionSet) {

        Application app = applicationAdminService.getApplication(appId);
        if (app == null) {
            log.warn("Unknown Application");
            return;
        }

        states.computeIf(appId,
                Objects::nonNull,
                (id, securityInfo) -> {
                    switch (securityInfo.getState()) {
                        case POLICY_VIOLATED:
                            System.out.println(
                                    "This application has violated the security policy. Please uninstall.");
                            return securityInfo;
                        case SECURED:
                            System.out.println(
                                    "The policy has been accepted already. To review policy, review [app.name]");
                            return securityInfo;
                        case INSTALLED:
                            System.out.println("Please review the security policy prior to accept them");
                            log.warn("Application has not been reviewed");
                            return securityInfo;
                        case REVIEWED:
                            return new SecurityInfo(permissionSet, SECURED);
                        default:
                            return securityInfo;
                    }
                });
    }

    private final class SecurityStateListener
            implements MapEventListener<ApplicationId, SecurityInfo> {

        @Override
        public void event(MapEvent<ApplicationId, SecurityInfo> event) {

            if (delegate == null) {
                return;
            }
            ApplicationId appId = event.key();
            SecurityInfo info = event.value().value();

            if (event.type() == MapEvent.Type.INSERT || event.type() == MapEvent.Type.UPDATE) {
                switch (info.getState()) {
                    case POLICY_VIOLATED:
                        notifyDelegate(new SecurityModeEvent(SecurityModeEvent.Type.POLICY_VIOLATED, appId));
                        break;
                    case SECURED:
                        notifyDelegate(new SecurityModeEvent(SecurityModeEvent.Type.POLICY_ACCEPTED, appId));
                        break;
                    default:
                        break;
                }
            } else if (event.type() == MapEvent.Type.REMOVE) {
                removeAppFromDirectories(appId);
            }
        }
    }

    private void removeAppFromDirectories(ApplicationId appId) {
        for (String location : localAppBundleDirectory.get(appId)) {
            localBundleAppDirectory.get(location).remove(appId);
        }
        violations.remove(appId);
        states.remove(appId);
        localAppBundleDirectory.remove(appId);
    }

    @Override
    public boolean registerApplication(ApplicationId appId) {
        Application app = applicationAdminService.getApplication(appId);
        if (app == null) {
            log.warn("Unknown application.");
            return false;
        }
        localAppBundleDirectory.put(appId, getBundleLocations(app));
        for (String location : localAppBundleDirectory.get(appId)) {
            if (!localBundleAppDirectory.containsKey(location)) {
                localBundleAppDirectory.put(location, new HashSet<>());
            }
            if (!localBundleAppDirectory.get(location).contains(appId)) {
                localBundleAppDirectory.get(location).add(appId);
            }
        }
        states.put(appId, new SecurityInfo(Sets.newHashSet(), INSTALLED));
        return true;
    }

    @Override
    public void unregisterApplication(ApplicationId appId) {
        if (localAppBundleDirectory.containsKey(appId)) {
            for (String location : localAppBundleDirectory.get(appId)) {
                if (localBundleAppDirectory.get(location).size() == 1) {
                    localBundleAppDirectory.remove(location);
                } else {
                    localBundleAppDirectory.get(location).remove(appId);
                }
            }
            localAppBundleDirectory.remove(appId);
        }
    }

    @Override
    public SecurityModeState getState(ApplicationId appId) {
        return states.asJavaMap().getOrDefault(appId, new SecurityInfo(null, null)).getState();
    }

    private Set<String> getBundleLocations(Application app) {
        Set<String> locations = new HashSet<>();
        for (String name : app.features()) {
            try {
                Feature feature = featuresService.getFeature(name);
                locations.addAll(
                        feature.getBundles().stream().map(BundleInfo::getLocation).collect(Collectors.toList()));
            } catch (Exception e) {
                return locations;
            }
        }
        return locations;
    }
}
