package com.tandbergtv.workflow.auth;

import java.io.File;
import java.security.Principal;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.naming.InitialContext;

import org.apache.log4j.Logger;

import com.tandbergtv.neptune.authorization.entity.IModule;
import com.tandbergtv.neptune.authorization.entity.IPermission;
import com.tandbergtv.neptune.authorization.service.IAuthorizationService;
import com.tandbergtv.workflow.core.service.Service;

/**
 * The default credential management implementation
 * 
 * @author spuranik
 */
public class CredentialsManager implements ICredentialsManager, Service {
	
	private static final Logger logger = Logger.getLogger(CredentialsManager.class);
	
	private Map<String, Module> modules = new HashMap<String, Module>();
	
	private List<File> authFiles;
	
	private String name;
	
	/**
	 * Creates a CredentialsManager
	 */
	public CredentialsManager(List<File> authFiles, String name) {
		this.authFiles = authFiles;
		this.name = name;
	}

	/* (non-Javadoc)
	 * @see com.tandbergtv.workflow.core.service.ServiceLifecycle#start()
	 */
	@Override
	public void start() {
		// set the modules from the list of modules in the file given on startup
		for (File file : authFiles) {
			for (Module module : AuthorizationConfReader.getInstance().read(
					file))
				modules.put(module.getName(), module);
			logger.info("Credentials manager initialized, cached "
					+ this.modules.size() + " modules");
		}
	}

	/* (non-Javadoc)
	 * @see com.tandbergtv.workflow.core.service.ServiceLifecycle#stop()
	 */
	@Override
	public void stop() {
		logger.debug("Credentials manager destroyed");
	}
	
	/* (non-Javadoc)
	 * @see com.tandbergtv.workflow.core.service.Service#getServiceName()
	 */
	@Override
	public String getServiceName() {
		return name;
	}


	/* (non-Javadoc)
	 * @see com.tandbergtv.workflow.auth.ICredentialsManager#getCredentials(java.security.Principal)
	 */
	public Credentials getCredentials(Principal principal) throws CredentialException {
		Set<String> actions = new HashSet<String>(); 
		Set<String> sections = new HashSet<String>();
		Set<String> menus = new HashSet<String>();

		try {
			InitialContext context = new InitialContext();
			IAuthorizationService neptuneAuthService = (IAuthorizationService) context
					.lookup("/cms/AuthorizationService/local");
			Set<IModule> userModules = neptuneAuthService.getAuthorizedPermissionsByModule();
			logger.debug("userModules.size()=" + userModules.size());
			
			for (IModule userModule: userModules) {
				logger.debug("userModule = " + userModule.getName());
				
				Module module = modules.get(userModule.getName());
				if(module != null) {
					for(IPermission userPermission : userModule.getPermissions()) {
						logger.debug("userPermission = " + userPermission.getName());
						
						Permission permission = module.getPermission(userPermission.getName());
						if(permission != null) {
							actions.addAll(permission.getActions());
							sections.addAll(permission.getSections());
							menus.addAll(permission.getMenus());
						}
					}
				} else {
					/*
					 * Remember all section names irrespective of whether the module was found in 
					 * auth.xml or not.
					 */
					for(IPermission userPermission : userModule.getPermissions()) {
						sections.add(userPermission.getModuleName() + " " + userPermission.getName());
					}
				}
			}
			
			logger.debug("actions = " + actions);
			logger.debug("sections = " + sections);
			logger.debug("menus = " + sections);
			
		} catch (Exception e) {
			throw new CredentialException("Failed to get credentials", e);
		}
		
		return new Credentials(principal, actions, sections, menus);
	}
}
