package com.k_int.ciim.utils;

import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.orm.hibernate3.SessionFactoryUtils;

import com.k_int.ciim.json.CIIMUserJSON;
import com.k_int.svc.identity.datamodel.AuthenticationDetailsHDO;
import com.k_int.svc.identity.datamodel.RegisteredUserHDO;
import com.k_int.svc.identity.datamodel.RoleHDO;
import com.k_int.svc.identity.service.IdentityService;
import com.k_int.svc.identity.service.TargetObjectIdentifier;

public class IdentityServiceWrapper 
{
	private static Log log = LogFactory.getLog(IdentityServiceWrapper.class);
	
	public static boolean hasPermission(IdentityService identity_service, Long user_id, String permission, String target, String id)
	{
		boolean retval = false;
		
		TargetObjectIdentifier[] grants = identity_service.listGrantsFor(user_id, permission);
		
		if(grants != null &&  grants.length > 0)
		{
			for(TargetObjectIdentifier grant : grants)
			{
				if(target != null && grant.getTargetClassName() != null && grant.getTargetClassName().equalsIgnoreCase(target))
				{
					List<String> granted_ids = grant.getIdentifierComponents();
					
					if(granted_ids != null && granted_ids.size() > 0 && id != null && granted_ids.contains(id))
					{
						retval = true;
						break;
					}
				}
			}
		}
		
		return retval;
	}
	
	public static List<AuthenticationDetailsHDO> listAllUsers(IdentityService identity_service, SessionFactory factory)
	{
		List<AuthenticationDetailsHDO> retval = null;
		
		Session session = null;
		
		try 
		{
			session = SessionFactoryUtils.getSession(factory, true);
			
			Query q = session.createQuery("Select x from com.k_int.svc.identity.datamodel.AuthenticationDetailsHDO x");
  
			List<AuthenticationDetailsHDO> lAuths = (List<AuthenticationDetailsHDO>) q.list();
			
			if(lAuths != null && lAuths.size() > 0)
			{
				retval = new ArrayList<AuthenticationDetailsHDO>();
				
				for(AuthenticationDetailsHDO lAuth : lAuths)
				{
					if(lAuth != null)
					{
						RegisteredUserHDO lUser = lAuth.getUser();
						
						if(lUser != null)
						{
							Set<RoleHDO> lRoles = lUser.getRoles();
							  
							for(RoleHDO lRole : lRoles)
							{
								if(lRole != null && lRole.getName() != null)
								{
							  
								}
							}
						}
						retval.add(lAuth);
					}
				}
			}
		}
		catch (HibernateException he) 
		{
			log.error("[firstrun:1] Problem returning users from db", he);
		} 
		catch (Exception e) 
		{
			log.error("[firstrun:1] Problem returning users", e);
		} 
		
		return retval;
	}
	
	public static boolean enableUser(Long id, SessionFactory factory)
	{
		return updateUserActiveStatus(id, true, factory);
	}
	
	public static boolean disableUser(Long id, SessionFactory factory)
	{
		return updateUserActiveStatus(id, false, factory);
	}
		
	private static boolean updateUserActiveStatus(Long id, boolean active, SessionFactory factory)
	{
		boolean retval = false;
		
		Session session = null;
		
		try 
		{
			session = SessionFactoryUtils.getSession(factory, true);
			
			Query q = session.createQuery("Select distinct(x) from com.k_int.svc.identity.datamodel.AuthenticationDetailsHDO x where x.user.id = ?");
			q.setLong(0, id);
			
			AuthenticationDetailsHDO result = (AuthenticationDetailsHDO) q.uniqueResult();
			
			if(result != null && result.getUser() != null)
			{
				RegisteredUserHDO lUser = result.getUser();
				
				lUser.setActive(active);
				
				if(active == false)
				{
					//encode a new password using the MD5 encoded value of the users name
					byte[] bytesOfPwd = lUser.getName().getBytes("UTF-8"); 
					 
					MessageDigest md = MessageDigest.getInstance("MD5"); 
					byte[] thedigest = md.digest(bytesOfPwd); 
					
					String encodedPwd = new String(thedigest);
					
					result.setPassword(encodedPwd);
				}
				
				result.setUser(lUser);
				
				Transaction tx = session.beginTransaction();
				session.saveOrUpdate(result);
				session.flush();
				tx.commit();
				
				retval = true;
			}
			else
			{
				throw new NullPointerException("User does not exist");
			}
			
		}
		catch (HibernateException he) 
		{
			retval = false;
			log.error("[firstrun:1] Problem modifying active status for user", he);
		} 
		catch (Exception e) 
		{
			retval = false;
			log.error("[firstrun:1] Problem  modifying active status for user", e);
		} 
		
		return retval;
	}
	
	public static List<TargetObjectIdentifier> listGrantsFor(IdentityService identity_service, Long user_id, String permission)
	{
		List<TargetObjectIdentifier> retval = null;
		
		TargetObjectIdentifier[] grants = identity_service.listGrantsFor(user_id, permission);
		
		if(grants != null &&  grants.length > 0)
		{
			retval = new ArrayList<TargetObjectIdentifier>();
			
			for(TargetObjectIdentifier grant : grants)
			{
				retval.add(grant);
			}
		}
		
		return retval;
	}
	
	public static List<AuthenticationDetailsHDO> getAssignedAuthsInRole(String object_id, String role, SessionFactory factory)
	{
		Session session = null;
		  
		List<AuthenticationDetailsHDO> lReturn = new ArrayList<AuthenticationDetailsHDO>();
		  
		try 
		{
			session = SessionFactoryUtils.getSession(factory, true);
			  
			Query q = session.createQuery("Select y from com.k_int.svc.identity.datamodel.AuthenticationDetailsHDO y, com.k_int.svc.identity.datamodel.GrantHDO x where y.user.id = x.party.id and x.keys[0] = ?");
			q.setParameter(0, object_id);
		  
			List<AuthenticationDetailsHDO> results = (List<AuthenticationDetailsHDO>) q.list();
			
			if(results != null && results.size() > 0)
			{
				//log.debug("results returned : " + results.size());
				for(AuthenticationDetailsHDO auth : results)
				{
					if(auth != null && auth.getUser() != null && auth.getUser().getRoles() != null && auth.getUser().getRoles().size() > 0)
					{
						for(RoleHDO assigned_role : auth.getUser().getRoles())
						{
							if(role != null && assigned_role.getDescription() != null && assigned_role.getDescription().equalsIgnoreCase(role))
							{
								lReturn.add(auth);
								break;
							}
						}
					}
				}
			}
		}
		catch (HibernateException he) 
		{
			log.error("[firstrun:1] Problem returning users from db", he);
		} 
		catch (Exception e) 
		{
			log.error("[firstrun:1] Problem returning users", e);
		} 
		
		return lReturn;
	}
	
	public static List<CIIMUserJSON> getAssignedEditors(Session session, String gid)
	{
		List<CIIMUserJSON> retval = new ArrayList<CIIMUserJSON>();
		  
		Query q = session.createQuery("Select y from com.k_int.svc.identity.datamodel.AuthenticationDetailsHDO y, com.k_int.svc.identity.datamodel.GrantHDO x where y.user.id = x.party.id and x.keys[0] = ?");
		q.setParameter(0, gid);
		  
		List<AuthenticationDetailsHDO> lResults = (List<AuthenticationDetailsHDO>) q.list();
		    
		if(lResults != null && lResults.size() > 0)
		{			  
			for(AuthenticationDetailsHDO lUser : lResults)
			{
				if(lUser != null)
				{
					retval.add(CIIMUserJSON.userHDOtoDTO(lUser.getUser(), lUser.getUsername() , lUser.getPassword()));
				}
			}		  
		}
		
		return retval;
	}
}