/*
 *  Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 *  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.wso2.carbon.device.mgt.ios.listener;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.CarbonConstants;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.user.api.AuthorizationManager;
import org.wso2.carbon.user.api.Permission;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.api.UserStoreManager;
import org.wso2.carbon.user.core.service.RealmService;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class IOSPermissionUpdateListener implements ServletContextListener {

    private static Log log = LogFactory.getLog(IOSPermissionUpdateListener.class);

    public static final String PERM_ENROLL_IOS = "/permission/admin/device-mgt/devices/enroll/ios";
    public static final String PERM_OWNING_DEVICE = "/permission/admin/device-mgt/devices/owning-device";

    public static final String ADD = "/add";
    public static final String MODIFY = "/modify";
    public static final String EVENT = "/event";
    public static final String MANAGE_ALERTS = "/manage-alerts";
    public static final String REMOVE = "/remove";
    public static final String VIEW = "/view";
    public static final String OPERATIONS = "/operations/ios";
    public static final String VIEW_ANALYTICS = "/view-analytics";

    public static final String ROLE_NAME = "internal/devicemgt-user";

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {

        UserStoreManager userStoreManager = getUserStoreManager();
        try {
            if (userStoreManager != null) {
                if (!userStoreManager.isExistingRole(ROLE_NAME)) {
                    userStoreManager.addRole(ROLE_NAME, null, getPermissions());
                } else {
                    getAuthorizationManager().authorizeRole(ROLE_NAME,
                            PERM_ENROLL_IOS, CarbonConstants.UI_PERMISSION_ACTION);
                    getAuthorizationManager().authorizeRole(ROLE_NAME,
                            PERM_OWNING_DEVICE + ADD, CarbonConstants.UI_PERMISSION_ACTION);
                    getAuthorizationManager().authorizeRole(ROLE_NAME,
                            PERM_OWNING_DEVICE + MODIFY, CarbonConstants.UI_PERMISSION_ACTION);
                    getAuthorizationManager().authorizeRole(ROLE_NAME,
                            PERM_OWNING_DEVICE + EVENT, CarbonConstants.UI_PERMISSION_ACTION);
                    getAuthorizationManager().authorizeRole(ROLE_NAME,
                            PERM_OWNING_DEVICE + MANAGE_ALERTS, CarbonConstants.UI_PERMISSION_ACTION);
                    getAuthorizationManager().authorizeRole(ROLE_NAME,
                            PERM_OWNING_DEVICE + REMOVE, CarbonConstants.UI_PERMISSION_ACTION);
                    getAuthorizationManager().authorizeRole(ROLE_NAME,
                            PERM_OWNING_DEVICE + VIEW, CarbonConstants.UI_PERMISSION_ACTION);
                    getAuthorizationManager().authorizeRole(ROLE_NAME,
                            PERM_OWNING_DEVICE + OPERATIONS, CarbonConstants.UI_PERMISSION_ACTION);
                    getAuthorizationManager().authorizeRole(ROLE_NAME,
                            PERM_OWNING_DEVICE + VIEW_ANALYTICS, CarbonConstants.UI_PERMISSION_ACTION);
                }
            } } catch (UserStoreException e) {
            log.error("Error while creating a role and adding a user for IOS.", e);
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }

    public static UserStoreManager getUserStoreManager() {
        RealmService realmService;
        UserStoreManager userStoreManager;
        try {
            PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
            realmService = (RealmService) ctx.getOSGiService(RealmService.class, null);
            if (realmService == null) {
                String msg = "Realm service has not initialized.";
                log.error(msg);
                throw new IllegalStateException(msg);
            }
            int tenantId = ctx.getTenantId();
            userStoreManager = realmService.getTenantUserRealm(tenantId).getUserStoreManager();
            realmService.getTenantUserRealm(tenantId).getAuthorizationManager();
        } catch (UserStoreException e) {
            String msg = "Error occurred while retrieving current user store manager";
            log.error(msg, e);
            throw new IllegalStateException(msg);
        }
        return userStoreManager;
    }

    public static AuthorizationManager getAuthorizationManager() {
        RealmService realmService;
        AuthorizationManager authorizationManager;
        try {
            PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
            realmService = (RealmService) ctx.getOSGiService(RealmService.class, null);
            if (realmService == null) {
                String msg = "Realm service has not initialized.";
                log.error(msg);
                throw new IllegalStateException(msg);
            }
            int tenantId = ctx.getTenantId();
            authorizationManager = realmService.getTenantUserRealm(tenantId).getAuthorizationManager();
        } catch (UserStoreException e) {
            String msg = "Error occurred while retrieving current user store manager";
            log.error(msg, e);
            throw new IllegalStateException(msg);
        }
        return authorizationManager;
    }

    private Permission[] getPermissions() {

            Permission ios = new Permission(PERM_ENROLL_IOS, CarbonConstants.UI_PERMISSION_ACTION);
            Permission add = new Permission(PERM_OWNING_DEVICE + ADD, CarbonConstants.UI_PERMISSION_ACTION);
            Permission modify = new Permission(PERM_OWNING_DEVICE + MODIFY, CarbonConstants.UI_PERMISSION_ACTION);
            Permission event = new Permission(PERM_OWNING_DEVICE + EVENT, CarbonConstants.UI_PERMISSION_ACTION);
            Permission alert = new Permission(PERM_OWNING_DEVICE + MANAGE_ALERTS, CarbonConstants.UI_PERMISSION_ACTION);
            Permission remove = new Permission(PERM_OWNING_DEVICE + REMOVE, CarbonConstants.UI_PERMISSION_ACTION);
            Permission view = new Permission(PERM_OWNING_DEVICE + VIEW, CarbonConstants.UI_PERMISSION_ACTION);
            Permission operations = new Permission(PERM_OWNING_DEVICE + OPERATIONS, CarbonConstants.UI_PERMISSION_ACTION);
            Permission analytics = new Permission(PERM_OWNING_DEVICE + VIEW_ANALYTICS, CarbonConstants
                    .UI_PERMISSION_ACTION);
            return new Permission[]{ios, add, modify, event, alert, remove, view, operations, analytics};
    }

}
