/*
 * Copyright 2015 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.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);
                    print("[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) {
            print("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 void print(String format, Object... args) {
        System.out.println(String.format("SM-ONOS: " + format, args));
        log.warn(String.format(format, args));
    }

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

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

    }


}