/* ======================================================================
   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.servlet.facilities;

import org.apache.log4j.Logger;

import org.bodington.servlet.*;

import org.bodington.database.*;
import org.bodington.server.*;
import org.bodington.server.realm.*;

import java.io.*;
import java.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;

import java.util.*;

import org.bodington.server.resources.Resource;

public class AliasFacility extends org.bodington.servlet.facilities.Facility
	{
    
    private static Logger log = Logger.getLogger(AliasFacility.class);
	
	public Resource newResource()
		{
		return new AliasEditor();
		}
	
	public List initResource( HttpServletRequest breq, Resource newResource )
		{
		if ( !(newResource instanceof AliasEditor) )
			throw new IllegalArgumentException( "Technical problem: An incorrect type of resource was created." );
        List errors = super.initResource(breq, newResource);
		return errors;
		}

	

	public void insert( Request req, PrintWriter out, String command, String insertname )
		throws ServletException, IOException
		{
		AliasEditor editor;
		
		log.debug( " AliasFacility insert( " + command + ", " + insertname + " )");

			
		if ( command.equalsIgnoreCase( "zonename" ) )
		    {
		    if ( out==null ) return;
	    	try
	    		{
		        editor = (AliasEditor)req.getResource();
		      	if ( editor == null )
		            return;
		        Zone zone = editor.getEffectiveZone();
		        if ( zone!=null )
		        	out.print( zone.getName() );
		    	}
		    catch ( Exception ex )
		        {
		        out.print( ex.toString() );
		        return;
		        }
		    }
		    
		if ( command.equalsIgnoreCase( "aliases" ) )
		    {
		    if ( out==null ) return;
	    	try
	    		{
			    Alias alias;

		        editor = (AliasEditor)req.getResource();
		      	if ( editor == null )
		            return;
	        
	        	Enumeration enumeration = editor.findEditableAliases();
		        
	        	out.println( "<TABLE CLASS=bs-table-opaque><TR>" );
	        	out.println( "<TD CLASS=bs-cell-special><B>Edit</B></TD>" );
	        	out.println( "<TD CLASS=bs-cell-special><B>Name</B></TD>" );
	        	out.println( "<TD CLASS=bs-cell-special><B>Primary</B></TD>" );
	        	out.println( "<TD CLASS=bs-cell-special><B>User Category</B></TD>" );
	        	out.println( "<TD CLASS=bs-cell-special><B>Has Entries</B></TD>" );
	        	out.println( "<TD CLASS=bs-cell-special><B>Add Entries</B></TD>" );
	        	out.println( "<TD CLASS=bs-cell-special><B>Clear Entries</B></TD></TR>" );
		        
	        	Integer a;
	        	boolean primary;
	        	while ( enumeration.hasMoreElements() )
	        		{
	        		alias = (Alias)enumeration.nextElement();
	        		out.print( "<TD ALIGN=CENTER VALIGN=CENTER><FONT SIZE=-2>" );
	        		out.print( "<FORM METHOD=POST ACTION=bs_template_editalias.html>" );
	        		out.print( "<INPUT TYPE=HIDDEN NAME=alias_id VALUE=" );
                    out.print( alias.getAliasId().toString() );
                    out.print( "><INPUT TYPE=SUBMIT VALUE=Edit></FORM></FONT>" );
	        		
	        		out.println( "</TD><TD>" );
                    out.print( alias.getAliasName() );
	        		out.println( "</TD><TD>" );
	        		
	        		a = alias.getAliasType(); 
	        		primary = ( a!=null && a.intValue() == Alias.TYPE_PRIMARY );
	        		if ( primary )
	        			{
	        			out.print( "yes" );
	        			out.print( "</TD><TD>" );
	        			out.print( alias.getUserCategory() );
	        			}
	        		else
	        			out.print( "~</TD><TD>~" );
        			out.print( "</TD><TD>" );
	        		if ( alias.hasEntries() )
	        			out.println( "Yes" );
	        		else
	        			out.println( "No" );

	        		out.print( "</TD><TD><FONT SIZE=-2>" );
	        		out.print( "<FORM METHOD=POST ACTION=bs_template_createaliasentries.html>" );
	        		out.print( "<INPUT TYPE=HIDDEN NAME=alias_id VALUE=" );
                    out.print( alias.getAliasId().toString() );
                    out.print( "><INPUT TYPE=SUBMIT VALUE=Add></FORM>" );
	        		out.print( "</FONT></TD><TD><FONT SIZE=-2>" );
	        		out.print( "<FORM METHOD=POST ACTION=bs_template_clearaliasentries.html>" );
	        		out.print( "<INPUT TYPE=HIDDEN NAME=alias_id VALUE=" );
                    out.print( alias.getAliasId().toString() );
                    out.print( "><INPUT TYPE=SUBMIT VALUE=Clear></FORM>" );
        			out.print( "</FONT></TD></TR>" );
	        		}
		        
	        	out.println( "<TR><TD COLSPAN=7><A HREF=bs_template_createalias.html><I>Create new type of unique identifier.</I></A></TD></TR></TABLE>" );
		        }
		    catch ( Exception ex )
		        {
		        out.print( ex.toString() );
		        return;
		        }
	        
		    return;
		    }

		if ( command.equalsIgnoreCase( "aliasnamecontrol" ) )
		    {
		    if ( out==null ) return;
		    return;
		    }

		if ( command.equalsIgnoreCase( "aliasfield" ) || 
			 command.equalsIgnoreCase( "aliasname" )      )
		    {
		    if ( out==null ) return;
		    try
		    	{
		        editor = (AliasEditor)req.getResource();
		      	if ( editor == null )
		            return;
		    	Alias alias=null;
				String aid=(String)req.getParameter( "alias_id" );
				if ( aid!=null && aid.length()>0 )
					{
					PrimaryKey k;
					k = new PrimaryKey( Integer.parseInt( aid ) );
					alias = Alias.findAlias( k );
					if ( alias==null )
						{
						out.println( "<P>Selected alias wasn't found.</P>" );
						return;
						}
					if ( !alias.getZoneId().equals( editor.getEffectiveZoneId() ) )
						{
						out.println( "<P>Selected alias doesn't belong in this administrative zone.</P>" );
						return;
						}
					}
				if ( command.equalsIgnoreCase( "aliasname" ) )
					out.print( alias.getAliasName() );
				else
		    		aliasField( req, out, insertname, alias );
		        }
		    catch ( Exception ex )
		        {
		        out.print( ex.toString() );
		        return;
		        }
		        
		    return;
		    }

		if ( command.equalsIgnoreCase( "aliasoperation" ) )
		    {
		    if ( out==null ) return;
		    String aliasop = req.getParameter( "aliasop" );
		    if ( aliasop==null || aliasop.length()<1 )
		    	return;
		    if ( aliasop.equalsIgnoreCase( "noop" ) )
		    	return;
		    	
		    try 
		        {
		        editor = (AliasEditor)req.getResource();
		        if ( editor == null )
		            return;

    		        
	            Alias alias=null;
	            PrimaryKey alias_id=null;
	           	String str = req.getParameter( "alias_id" );
	          	if ( str!=null && str.length()>0 )
		       		{
			       	alias_id = new PrimaryKey( Integer.parseInt( str ) );
			       	if ( alias_id!=null )
	            		alias = Alias.findAlias( alias_id );
	            	if ( alias==null )
	            		{
		            	out.println( "ERROR The specified unique identifier couldn't be found.</FONT></P>" );
		            	return;
	            		}
	            	if ( !alias.getZone().equals( editor.getEffectiveZone() ) )
	            		{
		            	out.println( "ERROR The specified unique identifier doesn't belong in this administrative zone.</FONT></P>" );
		            	return;
	            		}
	            	}
    		    
		        if ( aliasop.equalsIgnoreCase( "deletealias" ) )
		        	{
					out.print( "<P><FONT COLOR=RED>Confirmation: " );
		            if ( alias==null )
	            		{
		            	out.println( "ERROR No unique identifier was selected for deletion.</FONT></P>" );
		            	return;
	            		}
	            	if ( alias.hasEntries() )
	            		{
		            	out.println( "ERROR The unique identifier cannot be deleted because it has entries..</FONT></P>" );
		            	return;
	            		}
	            	alias.delete();
	            	out.println( " Alias deleted.</FONT></P>" );
	            	return;
		        	}
		        	
		        if ( aliasop.equalsIgnoreCase( "clearaliasentries" ) )
		        	{
					out.print( "<P><FONT COLOR=RED>Confirmation: " );
		            if ( alias==null )
	            		{
		            	out.println( "ERROR No unique identifier was selected for deletion.</FONT></P>" );
		            	return;
	            		}
	            		
	            	String c = req.getParameter( "certain" );
	            	if ( c==null || !c.equalsIgnoreCase( "yes" ) )
	            		{
		            	out.println( "ERROR operation wasn't carried out because the confirmation checkbox wasn't selected.</FONT></P>" );
		            	return;
	            		}
	            		
	            	if ( !alias.hasEntries() )
	            		{
		            	out.println( "There are no entries left to clear.</FONT></P>" );
		            	return;
	            		}
	            		
	            	AliasEntry entry;
	            	Enumeration enumeration = AliasEntry.findAliasEntries( "alias_id = " + alias.getAliasId() );
	            	while ( enumeration.hasMoreElements() )
	            		{
	            		entry = (AliasEntry) enumeration.nextElement();
	            		entry.delete();
	            		}
	            	out.println( " unique identifier entries deleted.</FONT></P>" );
		        	}
		        	
		        if ( aliasop.equalsIgnoreCase( "createalias" ) || 
		             aliasop.equalsIgnoreCase( "editalias" )        )
		            {
					out.print( "<P><FONT COLOR=RED>Confirmation: " );
					out.flush();
					
			        if ( aliasop.equalsIgnoreCase( "editalias" ) && alias==null )
		            	{
			            out.println( "ERROR No unique identifier was selected for editing.</FONT></P>" );
			            return;
		            	}
		            
		            String name = req.getParameter( "alias_name" );
		            if ( name==null )
		            	{
		            	out.println( "ERROR The unique identifier name was not specified.</FONT></P>" );
		            	return;
		            	}
		            name = name.toLowerCase().trim();

		            String type = req.getParameter( "alias_type" );
		            boolean is_primary = ( type!=null && type.equalsIgnoreCase( "primary" ) );
					if ( is_primary )
		            	{
		            	String[] user_cats = req.getParameterValues( "category" );
		            	String user_cat="";
		            	if ( user_cats==null || user_cats.length==0 )
		            		{
		            		out.println( "ERROR For primary unique identifiers one or more user categories must be specified.</FONT></P>" );
		            		return;
		            		}
		            	for ( int i=0; i< user_cats.length; i++ )
		            		{
		            		if ( i>0 )
		            			user_cat+=",";
		            		user_cat += user_cats[i];
		            		}
			            	
				        if ( aliasop.equalsIgnoreCase( "editalias" ) )
				        	{
				            editor.editAlias( alias_id, name, true, user_cat );
				            out.println( "Edits saved.</FONT></P>" );
				            }
				        else
				        	{
			            	editor.createAlias( name, true, user_cat );
				            out.println( "New alias created.</FONT></P>" );
			            	}
			            return;
		            	}
		            	

			        if ( aliasop.equalsIgnoreCase( "editalias" ) )
			        	{
			            editor.editAlias( alias_id, name, false, null );
			            out.println( "Edits saved.</FONT></P>" );
			            }
			        else
			        	{
			            editor.createAlias( name, false, null );
			            out.println( "New alias created.</FONT></P>" );
			            }
			        return;
		            }

		        if ( aliasop.equalsIgnoreCase( "createaliasentries" ) )
		            {
					out.print( "<P><FONT COLOR=RED>Confirmation: " );
		            String name = alias.getAliasName();
		            String entries = req.getParameter( "alias_entries" );
		            editor.createAliasEntries( name, new BufferedReader( new StringReader( entries ) ) );
		            out.println( "Identifiers were successfully created.</FONT></P>" );
		            }
		        }
		    catch ( Exception ex )
		        {
		        out.println( "</FONT></P>" );
			logException( out, "AliasFacility", "insert", 
			    "A technical problem occurred.",
			    ex );
		        return;
		        }
		    return;
		    }


		if ( command.equalsIgnoreCase( "ifaliashasentries" ) )
		    {
		    try
		    	{
		        editor = (AliasEditor)req.getResource();
		      	if ( editor == null )
		      		{
					req.setSwitchedOff(  true );
		            return;
		            }
		    	Alias alias=null;
				String aid=(String)req.getParameter( "alias_id" );
				if ( aid==null || aid.length()==0 )
					{
					req.setSwitchedOff(  true );
					return;
					}

				PrimaryKey k;
				k = new PrimaryKey( Integer.parseInt( aid ) );
				alias = Alias.findAlias( k );
				if ( alias==null )
					{
					req.setSwitchedOff(  true );
					return;
					}

				if ( !alias.getZoneId().equals( editor.getEffectiveZoneId() ) )
					{
					req.setSwitchedOff(  true );
					return;
					}

				req.setSwitchedOff(  !alias.hasEntries() );
		        }
		    catch ( Exception ex )
		        {
				req.setSwitchedOff(  true );
		        return;
		        }
		        
		    return;
		    }
		
		if ( command.equalsIgnoreCase( "aliascontrol" ) )
		   {
			try
				{
				BuildingSession session;
				UserManagementSession um_session;

		   	session = BuildingSessionManagerImpl.getSession( req.getResource() );
		   	if ( !(session instanceof UserManagementSession) )
		    		{
		    		out.println( "<HR>Technical problem: unable to access appropriate tool session.<HR>" );
		    		return;
		    		}
		   	um_session = (UserManagementSession)session;

				aliasControl( um_session, req, out );
	    		return;
		   	}
			catch ( BuildingServerException bsex )
				{
				out.println( bsex.toString() );
				return;
				}
		   }

			
		super.insert( req, out, command, insertname );
		}
	
	public void aliasField( Request req, 
							PrintWriter out, 
							String insertname, 
							Alias alias )
		throws IOException, BuildingServerException
		{
		StringBuffer where = new StringBuffer();
		
		
		   
		if ( insertname.equalsIgnoreCase( "alias_id" ) )
			{
			out.print( "<INPUT TYPE=HIDDEN NAME=alias_id VALUE=\"" );
			if ( alias!=null )
				out.print( alias.getAliasId().toString() );
			out.print( "\">" );
			}
			
		if ( insertname.equalsIgnoreCase( "alias_name" ) )
			{
			out.print( "<INPUT NAME=alias_name VALUE=\"" );
			if ( alias!=null )
				out.print( alias.getAliasName() );
			out.print( "\">" );
			}
			
		if ( insertname.equalsIgnoreCase( "alias_type" ) )
			{
			out.print( "<INPUT TYPE=RADIO NAME=alias_type VALUE=Primary" );
			if ( alias!=null && alias.isPrimary() )
				out.print( " CHECKED" );
			out.println( " ONCLICK=\"doPrimary()\">Primary.<BR>" );
			out.print( "<INPUT TYPE=RADIO NAME=alias_type VALUE=Other" );
			if ( alias==null || !alias.isPrimary() )
				out.print( " CHECKED" );
			out.print( " ONCLICK=\"doSecondary()\">Secondary." );
			}
			
		if ( !insertname.equalsIgnoreCase( "user_categories" ) )
			return;
			
		Enumeration enumeration = Group.findGroups( "name LIKE 'all%'" );
		Group group;
		String name;
		for ( int i=0; enumeration.hasMoreElements(); i++ )
		    {
		    group = (Group)enumeration.nextElement();
		    name = group.getName();
		    //skip any groups that are not at top level
		    if ( name.indexOf( '.' )>=0 )
		        continue;
		    if ( name.equals( "allusers" ) )
		        continue;
		    name = name.substring( 3, name.length() );
		    out.print( "<INPUT TYPE=CHECKBOX NAME=category VALUE=\"" );
		    out.print( name );
		    out.print( "\"" );
		    if ( alias!=null && alias.hasUserCategory( name ) )
		    	out.print( " CHECKED" );
		    out.print( " ONCLICK=\"doCategory()\">" );
		    out.print( name );
		    out.println( "<BR>" );
		    }
		}
	
	public void aliasControl( UserManagementSession um_session, Request req, PrintWriter out )
		throws ServletException, BuildingServerException, IOException
		{
		int i, j, k;
		PrimaryKey alias_id;
		String alias_name;
		Vector aliases, categories;
		
		try 
		    {
			aliases = um_session.findPermittedAliasIds();
			if ( aliases==null || aliases.size()==0 )
				{
				out.println( "<P>PROBLEM: there are no primary unique identifier types defined in this administrative zone.</P>" );
				return;
				}

			out.println( "<SELECT NAME=alias_name size=7 onchange=\"setcategories()\">" );
			for ( j=0; j<aliases.size(); j++ )
				{
				alias_id = (PrimaryKey)aliases.elementAt( j );
				alias_name = um_session.nameOfPermittedAlias( alias_id );
				out.print( "<OPTION VALUE=" );
				out.print( alias_name );
				out.print( ">" );
				out.print( alias_name );
				out.println( "</OPTION>" );
				}
			out.println( "</SELECT>" );


			out.println( "<SCRIPT LANGUAGE=JavaScript>" );
			out.println( "var listOfLists = new Array(" + j + ")" );
			
			String cat;
			for ( i=0; i<aliases.size(); i++ )
				{
				alias_id = (PrimaryKey)aliases.elementAt( i );
				alias_name = um_session.nameOfPermittedAlias( alias_id );
				out.print( "listOfLists[" + i + "]= new Array( " );
				categories = um_session.categoriesOfPermittedAlias( alias_id );
				for ( k=0; k<categories.size(); k++ )
					{
					cat = (String)categories.elementAt( k );
					if ( k>0 )
						out.print( ", " );
					out.print( "\"" );
					out.print( cat );
					out.print( "\"" );
					}
				out.println( " )" );
				}
			out.println( "</SCRIPT>" );
			}
		catch ( Exception ex )
		    {
		    out.print( ex.toString() );
		    return;
		    }
		}
			
    public boolean isSysadmin()
    {
        return true;
    }
		
	}


