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

import com.google.common.collect.Lists;

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;

import org.onosproject.app.ApplicationAdminService;
import org.onosproject.app.ApplicationState;
import org.onosproject.core.Application;
import org.onosproject.core.ApplicationId;

import org.onosproject.event.EventDeliveryService;
import org.onosproject.event.ListenerRegistry;
import org.onosproject.security.AppPermission;
import org.onosproject.security.SecurityAdminService;
import org.onosproject.security.store.SecurityModeEvent;
import org.onosproject.security.store.SecurityModeListener;
import org.onosproject.security.store.SecurityModeStore;
import org.onosproject.security.store.SecurityModeStoreDelegate;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServicePermission;
import org.osgi.service.log.LogEntry;
import org.osgi.service.log.LogListener;
import org.osgi.service.log.LogReaderService;
import org.osgi.service.permissionadmin.PermissionInfo;

import java.security.AccessControlException;
import java.security.Permission;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.osgi.service.permissionadmin.PermissionAdmin;
import org.slf4j.Logger;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * Security-Mode ONOS management implementation.
 *
 * Note: Activating Security-Mode ONOS has significant performance implications in Drake.
 *       See the wiki for instructions on how to activate it.
 */

@Component(immediate = true)
@Service
public class SecurityModeManager implements SecurityAdminService {

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

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected LogReaderService logReaderService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected EventDeliveryService eventDispatcher;

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

    protected final ListenerRegistry<SecurityModeEvent, SecurityModeListener>
            listenerRegistry = new ListenerRegistry<>();

    private final SecurityModeStoreDelegate delegate = new InternalStoreDelegate();

    private SecurityLogListener securityLogListener = new SecurityLogListener();

    private PermissionAdmin permissionAdmin = getPermissionAdmin();

    @Activate
    public void activate() {

        eventDispatcher.addSink(SecurityModeEvent.class, listenerRegistry);
        logReaderService.addLogListener(securityLogListener);

        if (System.getSecurityManager() == null) {
            log.warn("J2EE security manager is disabled.");
            deactivate();
            return;
        }
        if (permissionAdmin == null) {
            log.warn("Permission Admin not found.");
            deactivate();
            return;
        }
        store.setDelegate(delegate);

        log.info("Security-Mode Started");
    }

    @Deactivate
    public void deactivate() {
        eventDispatcher.removeSink(SecurityModeEvent.class);
        logReaderService.removeLogListener(securityLogListener);
        store.unsetDelegate(delegate);
        log.info("Stopped");

    }

    @Override
    public boolean isSecured(ApplicationId appId) {
        if (store.getState(appId) == null) {
            store.registerApplication(appId);
        }
        return store.isSecured(appId);
    }


    @Override
    public void review(ApplicationId appId) {
        if (store.getState(appId) == null) {
            store.registerApplication(appId);
        }
        store.reviewPolicy(appId);
    }

    @Override
    public void acceptPolicy(ApplicationId appId) {
        if (store.getState(appId) == null) {
            store.registerApplication(appId);
        }
        store.acceptPolicy(appId, DefaultPolicyBuilder.convertToOnosPermissions(getMaximumPermissions(appId)));
    }

    @Override
    public void register(ApplicationId appId) {
        store.registerApplication(appId);
    }

    @Override
    public Map<Integer, List<Permission>> getPrintableSpecifiedPermissions(ApplicationId appId) {
        return getPrintablePermissionMap(getMaximumPermissions(appId));
    }

    @Override
    public Map<Integer, List<Permission>> getPrintableGrantedPermissions(ApplicationId appId) {
        return getPrintablePermissionMap(
                DefaultPolicyBuilder.convertToJavaPermissions(store.getGrantedPermissions(appId)));
    }

    @Override
    public Map<Integer, List<Permission>> getPrintableRequestedPermissions(ApplicationId appId) {
        return getPrintablePermissionMap(
                DefaultPolicyBuilder.convertToJavaPermissions(store.getRequestedPermissions(appId)));
    }

    private class SecurityLogListener implements LogListener {
        @Override
        public void logged(LogEntry entry) {
            if (entry.getException() != null &&
                    entry.getException() instanceof AccessControlException) {
                String location = entry.getBundle().getLocation();
                Permission javaPerm =
                        ((AccessControlException) entry.getException()).getPermission();
                org.onosproject.security.Permission permission = DefaultPolicyBuilder.getOnosPermission(javaPerm);
                if (permission == null) {
                    log.warn("Unsupported permission requested.");
                    return;
                }
                store.getApplicationIds(location).stream().filter(
                        appId -> store.isSecured(appId) &&
                                appAdminService.getState(appId) == ApplicationState.ACTIVE).forEach(appId -> {
                    store.requestPermission(appId, permission);
                    log.debug("[POLICY VIOLATION] APP: %s / Bundle: %s / Permission: %s ",
                            appId.name(), location, permission.toString());
                });
            }
        }
    }

    private class InternalStoreDelegate implements SecurityModeStoreDelegate {
        @Override
        public void notify(SecurityModeEvent event) {
            if (event.type() == SecurityModeEvent.Type.POLICY_ACCEPTED) {
                setLocalPermissions(event.subject());
                log.info("{} POLICY ACCEPTED and ENFORCED", event.subject().name());
            } else if (event.type() == SecurityModeEvent.Type.POLICY_VIOLATED) {
                log.info("{} POLICY VIOLATED", event.subject().name());
            } else if (event.type() == SecurityModeEvent.Type.POLICY_REVIEWED) {
                log.info("{} POLICY REVIEWED", event.subject().name());
            }
            eventDispatcher.post(event);
        }
    }

    /**
     * TYPES.
     * 0 - APP_PERM
     * 1 - ADMIN SERVICE
     * 2 - NB_SERVICE
     * 3 - ETC_SERVICE
     * 4 - ETC
     * @param perms
     */
    private Map<Integer, List<Permission>> getPrintablePermissionMap(List<Permission> perms) {
        ConcurrentHashMap<Integer, List<Permission>> sortedMap = new ConcurrentHashMap<>();
        sortedMap.put(0, new ArrayList());
        sortedMap.put(1, new ArrayList());
        sortedMap.put(2, new ArrayList());
        sortedMap.put(3, new ArrayList());
        sortedMap.put(4, new ArrayList());
        for (Permission perm : perms) {
            if (perm instanceof ServicePermission) {
                if (DefaultPolicyBuilder.getNBServiceList().contains(perm.getName())) {
                    if (perm.getName().contains("Admin")) {
                        sortedMap.get(1).add(perm);
                    } else {
                        sortedMap.get(2).add(perm);
                    }
                } else {
                    sortedMap.get(3).add(perm);
                }
            } else if (perm instanceof AppPermission) {
                sortedMap.get(0).add(perm);
            } else {
                sortedMap.get(4).add(perm);
            }
        }
        return sortedMap;
    }

    private void setLocalPermissions(ApplicationId applicationId) {
        for (String location : store.getBundleLocations(applicationId)) {
            permissionAdmin.setPermissions(location, permissionsToInfo(store.getGrantedPermissions(applicationId)));
        }
    }

    private PermissionInfo[] permissionsToInfo(Set<org.onosproject.security.Permission> permissions) {
        List<PermissionInfo> result = Lists.newArrayList();
        for (org.onosproject.security.Permission perm : permissions) {
            result.add(new PermissionInfo(perm.getClassName(), perm.getName(), perm.getActions()));
        }
        PermissionInfo[] permissionInfos = new PermissionInfo[result.size()];
        return result.toArray(permissionInfos);
    }



    private List<Permission> getMaximumPermissions(ApplicationId appId) {
        Application app = appAdminService.getApplication(appId);
        if (app == null) {
            log.debug("Unknown application.");
            return null;
        }
        List<Permission> appPerms;
        switch (app.role()) {
            case ADMIN:
                appPerms = DefaultPolicyBuilder.getAdminApplicationPermissions(app.permissions());
                break;
            case USER:
                appPerms = DefaultPolicyBuilder.getUserApplicationPermissions(app.permissions());
                break;
            case UNSPECIFIED:
            default:
                appPerms = DefaultPolicyBuilder.getDefaultPerms();
                break;
        }

        return appPerms;
    }

    private PermissionAdmin getPermissionAdmin() {
        BundleContext context = getBundleContext();
        return (PermissionAdmin) context.getService(context.getServiceReference(PermissionAdmin.class.getName()));
    }

    private BundleContext getBundleContext() {
        return FrameworkUtil.getBundle(this.getClass()).getBundleContext();

    }


}