/* ======================================================================
   Parts Copyright 2006 University of Leeds, Oxford University, University of the Highlands and Islands.

   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.bodington.server.events;

import org.bodington.server.*;
import org.bodington.server.resources.Resource;
import org.bodington.sqldatabase.*;
import org.bodington.database.*;
import org.bodington.server.realm.Permission;
import org.bodington.server.realm.User;

import java.util.Enumeration;
import java.util.Vector;
import java.util.Hashtable;


public class UserEventSetup extends org.bodington.sqldatabase.SqlPersistentObject
	{

	/**
	 * Primary key of this entry.
	 */
	private PrimaryKey user_event_setup_id;

	/**
	 * The user_id of the user this entry refers to.
	 */
	private PrimaryKey user_id;

	private java.sql.Timestamp	cutoff_time;
	private java.sql.Timestamp	email_cutoff_time;
	private int 				email_frequency;


	//transient data....
	private Hashtable res_in, res_out;
	
	private UserEventSetupIndexKey[] ikeys;

        
	public static UserEventSetup findUserEventSetup( PrimaryKey key )
	    throws BuildingServerException
	    {
	    return (UserEventSetup)findPersistentObject( key, "org.bodington.server.events.UserEventSetup" );
	    }
	
	public static UserEventSetup findUserEventSetup( String where )
	    throws BuildingServerException
	    {
	    return (UserEventSetup)findPersistentObject( where, "org.bodington.server.events.UserEventSetup" );
	    }
	
	public static UserEventSetup findUserEventSetupByUserId( PrimaryKey user_id )
	    throws BuildingServerException
	    {
	    UserEventSetupIndexKey ikey = new UserEventSetupIndexKey();
	    ikey.setUserId( user_id );
	    return (UserEventSetup)findPersistentObject( ikey, "org.bodington.server.events.UserEventSetup" );
	    }

        public static Enumeration findUserEventSetups( String where )
	    throws BuildingServerException
	    {
	    return findPersistentObjects( where, "org.bodington.server.events.UserEventSetup" );
	    }
        
    /**
     * Attempt to find an existing UserEventSetup of create a new one
     * @param user The user who needs the event tracking.
     * @return The user event session. 
     */
    public static UserEventSetup findOrCreate(User user)
    	throws BuildingServerException
    	{
    	UserEventSetup ues = findUserEventSetupByUserId( user.getUserId() );
    	if ( ues == null )
    	{
    		ues = new UserEventSetup();
    		ues.setUser( user );
    		ues.save();
    	}
    	return ues;
    	}

	public UserEventSetup()
		{
		ikeys = new UserEventSetupIndexKey[1];
		ikeys[0] = new UserEventSetupIndexKey();
                cutoff_time = new java.sql.Timestamp( System.currentTimeMillis() );
		email_cutoff_time = new java.sql.Timestamp( System.currentTimeMillis() );
		email_frequency = 0;
		}
	

    public void setPrimaryKey(PrimaryKey key)
	    {
        setUserEventSetupId( key );
    	}

    public PrimaryKey getPrimaryKey()
    	{
        return getUserEventSetupId();
    	}

    public void setUserEventSetupId( PrimaryKey key )
	    {
	    user_event_setup_id = key;
	    setUnsaved();
	    }

    public PrimaryKey getUserEventSetupId()
	    {
        return user_event_setup_id;
	    }
	

    public void setUserId( PrimaryKey key )
	    {
	    user_id = key;
	    setUnsaved();
            ikeys[0].setUserId( key );
	    }

    public PrimaryKey getUserId()
	    {
        return user_id;
	    }
	
	public void setUser( User u )
		{
		setUserId( u.getUserId() );
		}
	public User getUser()
		throws BuildingServerException
		{
		return User.findUser( user_id );
		}



	public java.sql.Timestamp getCutoffTime()
		{
		return cutoff_time;
		}
	public void setCutoffTime( java.sql.Timestamp t )
		{
		cutoff_time = t;
        setUnsaved();
		}



	public java.sql.Timestamp getEMailCutoffTime()
		{
		return email_cutoff_time;
		}
	public void setEMailCutoffTime( java.sql.Timestamp t )
		{
		email_cutoff_time = t;
        setUnsaved();
		}


	public int getEMailFrequency()
		{
		return email_frequency;
		}
		
    public void setEMailFrequency( int n )
    	{
    	email_frequency = n;
        setUnsaved();
    	}


	public boolean containsResource( Resource resource )
		throws BuildingServerException
		{
		if ( resource==null ) return false;
		if ( user_id== null )
			throw new BuildingServerException( "Can't add resource to notifications for unknown user." );
		
		if ( res_in==null ) res_in = new Hashtable();
		if ( res_out==null ) res_out = new Hashtable();

		if ( res_in.containsKey( resource.getResourceId() ) )
			return true;
		
		if ( res_out.containsKey( resource.getResourceId() ) )
			return false;
			
		ResourceEventUser res_e_u = 
				ResourceEventUser.findResourceEventUser( 
						"user_id = " + user_id + " AND resource_id = " + resource.getResourceId() );
		
		if ( res_e_u ==null )
			res_out.put( resource.getResourceId(), resource.getResourceId() );
		else
			res_in.put( resource.getResourceId(), resource.getResourceId() );
			
		return ( res_e_u != null );
		}


	public void addResource( Resource resource )
		throws BuildingServerException
		{
		if ( resource==null ) return;
		if ( user_id== null )
			throw new BuildingServerException( "Can't add resource to notifications for unknown user." );
		
		if ( containsResource( resource ) )
			return;
			
		ResourceEventUser res_e_u;
		res_e_u = new ResourceEventUser();
		res_e_u.setUserId( user_id );
		res_e_u.setResource( resource );
		res_e_u.save();

		res_out.remove( resource.getResourceId() );
		res_in.put( resource.getResourceId(), resource.getResourceId() );
		}

	public void removeResource( Resource resource )
		throws BuildingServerException
		{
		if ( resource==null ) return;
		if ( user_id== null )
			throw new BuildingServerException( "Can't remove resource from notifications for unknown user." );
		
		if ( !containsResource( resource ) )
			return;
			
		ResourceEventUser res_e_u = 
				ResourceEventUser.findResourceEventUser( 
						"user_id = " + user_id + " AND resource_id = " + resource.getResourceId() );
						
		res_e_u.delete();
		
		res_in.remove( resource.getResourceId() );
		res_out.put( resource.getResourceId(), resource.getResourceId() );
		}

		
	public Enumeration findResourceIds()
		throws BuildingServerException
		{
		if ( user_id== null )
			throw new BuildingServerException( "Can't find resources for unknown user." );

		Vector resource_ids = new Vector();
		ResourceEventUser reu;
		
		Enumeration enumeration = ResourceEventUser.findResourceEventUsers( "user_id = " + user_id );
		while ( enumeration.hasMoreElements() )
			{
			reu  = (ResourceEventUser)enumeration.nextElement();
			resource_ids.addElement( reu.getResourceId() );
			}
		return resource_ids.elements();
		}
		
	public Enumeration findResources()
		throws BuildingServerException
		{
		Enumeration enumeration = findResourceIds();
		// if there are no resources on list return empty enumeration
		if ( !enumeration.hasMoreElements() )
    	    return enumeration;
		StringBuffer where = new StringBuffer();
		PrimaryKey resource_id;
		where.append( "resource_id IN ( " );
		for ( int i=0; enumeration.hasMoreElements(); i++ )
			{
			resource_id = (PrimaryKey)enumeration.nextElement();
			if ( i>0 )
				where.append( ", " );
			where.append( resource_id.toString() );
			}
		where.append( " )" );
		
		return Resource.findResources( where.toString(), "left_index" );
		}

	public Enumeration findEventsForResource( Resource resource )
		throws BuildingServerException
		{
		return findEventsForResource( resource, cutoff_time );
		}
		
	public Enumeration findEventsForResource( Resource resource, java.sql.Timestamp since )
		throws BuildingServerException
		{
		StringBuffer where = new StringBuffer();
		int importance=Event.IMPORTANCE_USER_MAX+1;
		
		User user = getUser();
		
		if ( resource.checkPermission( user, Permission.VIEW ) )
			importance = Event.IMPORTANCE_USER_MIN;
		
		if ( resource.checkPermission( user, Permission.MANAGE ) )
			importance = Event.IMPORTANCE_MANAGEMENT_MIN;
		
		if ( resource.checkPermission( user, Permission.ADMINISTER ) )
			importance = Event.IMPORTANCE_ADMIN_MIN;
		
		if ( resource.checkPermission( user, Permission.SYSADMIN ) )
			importance = Event.IMPORTANCE_SYSTEM_MIN;
		
		// uses standard JDBC SQL escape sequence for the timestamp
		// to make the JDBC driver convert to the right format string
		
		where.append( "event_time > {ts '" );
		where.append( since );
		where.append( "'} AND resource_id = " );
		where.append( resource.getResourceId() );
		where.append( " AND importance >= " );
		where.append( importance );
		
		return Event.findEvents( where.toString(), "event_time" );
		}
	
	public IndexKey[] getIndexKeys()
	    {
	    
	    if ( ikeys[0].getUserId() == null )
	        return null;

	    return ikeys;
	    }
	    
	public boolean matchesKey( IndexKey testikey )
	    {
	    return testikey.equals( ikeys[0] );
	    }



	}
