/* ======================================================================
   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 java.security.*;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

import org.bodington.server.BuildingContext;
import org.bodington.server.realm.*;
import org.bodington.server.realm.Permission;
import org.bodington.text.*;

public class PasswordFacility extends org.bodington.servlet.facilities.Facility
	{	
    
    private static Logger log = Logger.getLogger(PasswordFacility.class);
	
	public void insert( Request req, PrintWriter out, String command, String insertname )
		throws ServletException, IOException
		{
		log.debug( " PasswordFacility insert()" );
		
		if ( command.equals( "confirmpass" ) )
			{
			confirmpass(  req, out );
			return;
			}

		if ( command.equals( "userdata" ) )
			{
			userdata(  req, out, insertname );
			return;
			}

		if ( command.equals( "preferences" ) )
			{
			preferences(  req, out, insertname );
			return;
			}

		if ( command.equals( "interfaceform" ) )
			{
			interfaceform(  req, out );
			return;
			}

		if ( command.equals( "stylesheetform" ) )
			{
			stylesheetform(  req, out );
			return;
			}

		if ( command.equals( "confirmpreferences" ) )
			{
			confirmpreferences(  req, out );
			return;
			}

		super.insert( req, out, command, insertname );
		}
	
	private void confirmpass( Request req, PrintWriter out )
		throws IOException
		{
		String o, p, c, r;
		User user;
		PassPhrase pass;
		
		if ( !BuildingContext.getContext().checkPermission( Permission.EDIT ) )
			{
			out.println( "<HR><H4>You don't have permission to use this facility.  Sorry.</H4><HR>\n" );
			return;
			}


		o=req.getParameter( "oldpass" );
		p=req.getParameter( "pass" );
		c=req.getParameter( "confirm" );

		try
			{
			user = (User)BuildingContext.getContext().getUser();
			pass = PassPhrase.findPassPhrase( user );
			if ( pass==null )
				{
				out.println( "<HR><H4>There was a problem finding your user name and password data.</H4><HR>\n" );
				out.println( "<P>You can go <A HREF=bs_template_main.html>back</A> and try again.</P>" );
				return;
				}
			
			if ( !pass.isPassPhrase( o ) )
				{
				out.println( "<HR><H4>You didn't enter the correct current password and so you are not allowed to change it.</H4><HR>\n" );
				out.println( "<P>You can go <A HREF=bs_template_main.html>back</A> and try again.</P>" );
				return;
				}

			if ( p==null || c==null )
				{
				out.println( "<HR><H4>There was an unexpected problem processing input.  Sorry.</H4><HR>\n" );
				out.println( "<P>You can go <A HREF=bs_template_main.html>back</A> and try again.</P>" );
				return;
				}
			
			if ( p.length()==0 )
				{
				out.println( "<HR><H4>You didn't type anything in the new password box.</H4><HR>\n" );
				out.println( "<P>You can go <A HREF=bs_template_main.html>back</A> and try again.</P>" );
				return;
				}
			if ( p.length()<6 )
				{
				out.println( "<HR><H4>You didn't type a password that is long enough (must be 6 or more characters).</H4><HR>\n" );
				out.println( "<P>You can go <A HREF=bs_template_main.html>back</A> and try again.</P>" );
				return;
				}
			if ( c.length()==0 )
				{
				out.println( "<HR><H4>You didn't retype your new password in the second box.</H4><HR>\n" );
				out.println( "<P>You can go <A HREF=bs_template_main.html>back</A> and try again.</P>" );
				return;
				}
			if ( !c.equals(p) )
				{
				out.println( "<HR><H4>You typed different things in the two boxes.</H4><HR>\n" );
				out.println( "<P>You can go <A HREF=bs_template_main.html>back</A> and try again.</P>" );
				return;
				}

			pass.changePassPhrase( p );

			pass.save();
				
			out.println( 
				"<H4>Your new password has been stored.  " +
				"When you access another page in the building " +
				"you will be prompted to log in again.  You should use your " +
				"new password.</H4>" );
			}
		catch ( Exception ex )
			{
			out.println( "<HR><H4>There was a problem finding your user name and password data.</H4><HR>\n" );
			out.println( "<P>You can go <A HREF=bs_template_main.html>back</A> and try again.</P><PRE>" );
			out.println( ex.toString() );
			out.println( "</PRE>" );
			return;
			}
		}


	private void userdata( Request req, PrintWriter out, String item )
		throws IOException
		{
		String o, p, c, r;
		User user;
		
		try
			{
			user = (User)BuildingContext.getContext().getUser();
			if ( user == null )
				{
				out.println( "<I>Data not available</I>" );
				return;
				}
			
			if ( item.equalsIgnoreCase( "user_id" ) )
				{
				out.println( user.getUserId().toString() );
				return;
				}

			if ( item.equalsIgnoreCase( "name" ) )
				{
				out.println( user.getName() );
				return;
				}

			if ( item.equalsIgnoreCase( "surname" ) )
				{
				out.println( user.getSurname() );
				return;
				}

			if ( item.equalsIgnoreCase( "initials" ) )
				{
				out.println( user.getInitials() );
				return;
				}

			if ( item.equalsIgnoreCase( "user_name" ) )
				{
				PassPhrase pass = PassPhrase.findPassPhrase( user );
				if ( pass==null )
					{
					out.println( "<I>Not found.</I>" );
					return;
					}
				out.println( pass.getUserName() );
				return;
				}
            
			if ( item.equalsIgnoreCase( "web_auth_user" ) )
			    {
			    WebAuthUser webAuthUser = WebAuthUser.findWebAuthUser( user );
			    if ( webAuthUser==null )
			    {
			        out.println( "<I>Not found.</I>" );
			        return;
			    }
			    out.println( webAuthUser.getUserName() );
			    return;
			    }    

			out.println( "<I>Unknown data item</I>" );
			}
		catch ( Exception ex )
			{
			out.println( "<HR><H4>There was a problem finding your personal data.</H4><HR>\n" );
			return;
			}
		}


	private void preferences( Request req, PrintWriter out, String item )
		throws IOException
		{
		String o, p, c, r;
		User user;
		PassPhrase pass;
		
		try
			{
			user = (User)BuildingContext.getContext().getUser();
			if ( user == null )
				{
				out.println( "<I>Data not available</I>" );
				return;
				}
			
			if ( item.equalsIgnoreCase( "interface" ) )
				{
				String stylefilename;
				Metadatum m = Metadatum.findMetadatumByIdAndName( user.getUserId(), "preference.interface" );

				if ( m==null || m.getValue() == null )
	    			out.println( "graphical" );
				else
	    			out.println( m.getValue() );
				
				return;
				}

			if ( item.equalsIgnoreCase( "stylesheet" ) )
				{
				String stylefilename;
				Metadatum m = Metadatum.findMetadatumByIdAndName( user.getUserId(), "preference.stylesheet" );

				if ( m==null || m.getValue() == null )
				    stylefilename = "standard.css";
				else
				    stylefilename = m.getValue();
				
				out.println( stylefilename.substring( 0, stylefilename.indexOf( ".css" ) ) );
				return;
				}

			if ( item.equalsIgnoreCase( "stylesheetdescription" ) )
				{
				String stylefilename;
			    File file = new File ( BuildingContext.getProperty( "buildingservlet.templatedirectory" ) );
				file = new File( file, "style_default" + File.separator + "default" );

				Metadatum m = Metadatum.findMetadatumByIdAndName( user.getUserId(), "preference.stylesheet" );
				if ( m==null || m.getValue() == null )
				    stylefilename = "standard.css";
				else
				    stylefilename = m.getValue();
				    
				file = new File( file, stylefilename );
				    
				synchronized ( this )
				    {
				    if ( !file.exists() )
				        {
				        out.println( "<I>Unknown stylesheet file.</I>" );
				        return;
				        }
				    BufferedReader input = new BufferedReader( new FileReader( file ) );
				    String topline = input.readLine();
				    if ( topline==null || !topline.startsWith( "/*" ) )
				        out.println( "No information available on stylesheet." );
                    else
                        {
				        int a=2;
				        int b=topline.indexOf( "*/" );
    				    
				        if ( b == -1 )
				            b = topline.length();
    				        
			            out.print( topline.substring( a, b ) );

				        while ( b == topline.length() )
				            {
				            topline = input.readLine();
				            a=0;
				            b=topline.indexOf( "*/" );
				            if ( b == -1 )
				                b = topline.length();
				            out.print( topline.substring( a, b ) );
				            }
				        }
				    
				    input.close();
				    }
				
				out.print( "<P><I>View <A TARGET=_new HREF=bs_template_samplehtml" );
				out.print( stylefilename.substring( 0, stylefilename.indexOf( ".css" ) ) );
				out.print( ".html>sample text</A></I></P>" );
				
				return;
				}

			out.println( "<I>Unknown data item</I>" );
			}
		catch ( Exception ex )
			{
			logException( out, "PasswordFacility", "preferences", 
			    "There was a problem finding your preferences.",
			    ex );
			return;
			}
		}

    private class StylesheetFilter implements FilenameFilter
        {
        public boolean accept( File dir, String name )
            {
            return name.endsWith( ".css" );
            }
        }

	private void interfaceform( Request req, PrintWriter out )
		throws IOException
		{
		int i;
		User user;
		
		try
			{
			user = (User)BuildingContext.getContext().getUser();
			if ( user == null )
				{
				out.println( "<I>Data not available</I>" );
				return;
				}

			String stylefilename;
    		StringBuffer filename = new StringBuffer();
			String selectedstylefilename;
			Metadatum m = Metadatum.findMetadatumByIdAndName( user.getUserId(), "preference.interface" );

			boolean narrative = ( m!=null && m.getValue() != null && m.getValue().equalsIgnoreCase( "narrative" ) );

            out.println( "<FORM METHOD=POST ACTION=bs_template_preferences.html>" );
            out.println( "<INPUT TYPE=HIDDEN NAME=preference VALUE=interface>" );
            out.println( "<TABLE CLASS=bs-table-opaque>" );
            out.println( "<TR>" );
            out.println( "<TD CLASS=bs-cell-special><B>User Interface</B></TD>" );
            out.println( "<TD CLASS=bs-cell-special><B>Description</B></TD>" );
            out.println( "</TR>" );

            out.print( "<TR><TD VALIGN=TOP><B><INPUT TYPE=RADIO NAME=interface VALUE=graphical" );
            if ( !narrative )
                out.print( " CHECKED" );
            out.println( ">graphical</B></TD>" );
            out.println( "<TD VALIGN=TOP>" );
            out.println( "The graphical interface uses a layout of frames, menus with icons and terse text to" );
            out.println( "help you navigate the web site and use tools." );
            out.println( "</TD>" );
            out.println( "</TR>" );

            out.println( "<TR><TD VALIGN=TOP><B><INPUT TYPE=RADIO NAME=interface VALUE=narrative" );
            if ( narrative )
                out.print( " CHECKED" );
            out.println( ">narrative</B></TD>" );
            out.println( "<TD VALIGN=TOP>" );
            out.println( "The narrative interface is under development and incomplete." );
            out.println( "This user interface uses no graphics, frames or tables but provides instead" );
            out.println( "narrative style text.  It is designed for use with a web browser that has speech" );
            out.println( "synthesis capability.  " );
            out.println( "</TD>" );
            out.println( "</TR>" );

            out.println( "<TR><TD COLSPAN=2 VALIGN=TOP ALIGN=CENTER><INPUT TYPE=SUBMIT VALUE=\"Save Selection\">" );
            out.println( "</TD></TR></TABLE></FORM>" );
			
			}
		catch ( Exception ex )
			{
			logException( out, "PasswordFacility", "interfaceform", 
			    "There was a problem displaying the form.",
			    ex );
			return;
			}
		}


	private void stylesheetform( Request req, PrintWriter out )
		throws IOException
		{
		int i;
		User user;
		
		try
			{
			user = (User)BuildingContext.getContext().getUser();
			if ( user == null )
				{
				out.println( "<I>Data not available</I>" );
				return;
				}

			String stylefilename;

			File file;
			File folder = new File ( BuildingContext.getProperty( "buildingservlet.templatedirectory" ) );
			folder = new File( folder, "style_default" + File.separator + "default" );

			String selectedstylefilename;
			Metadatum m = Metadatum.findMetadatumByIdAndName( user.getUserId(), "preference.stylesheet" );

			if ( m==null || m.getValue() == null )
				selectedstylefilename = "standard.css";
			else
				selectedstylefilename = m.getValue();
				
			synchronized ( this )
				{
                if ( !folder.exists() || !folder.isDirectory() )
                    {
                    out.println( "Technical problem - can't find style sheet options." );
                    return;
                    }
    				

		        String[] filenames = folder.list( new StylesheetFilter() );
    				    
		        if ( filenames == null || filenames.length == 0 )
                    {
                    out.println( "There are no style sheets to choose from." );
                    return;
                    }
		        
		        
		        out.println( "<FORM METHOD=POST ACTION=bs_template_preferences.html>" );
		        out.println( "<INPUT TYPE=HIDDEN NAME=preference VALUE=stylesheet>" );
                out.println( "<TABLE CLASS=bs-table-opaque>" );
                out.println( "<TR>" );
                out.println( "<TD CLASS=bs-cell-special><B>Stylesheet</B></TD>" );
                out.println( "<TD CLASS=bs-cell-special><B>Description</B></TD>" );
                out.println( "</TR>" );

		        
		        for ( i=0; i< filenames.length; i++ )
		            {
		            out.print( "<TR><TD VALIGN=TOP><B><INPUT TYPE=RADIO NAME=stylesheet VALUE=" );
		            out.print( filenames[i] );
		            if ( selectedstylefilename.equals( filenames[i] ) )
    		            out.print( " CHECKED>" );
    		        else
    		            out.print( " >" );
				    out.print( filenames[i].substring( 0, filenames[i].indexOf( ".css" ) ) );
		            out.println( "</B></TD><TD VALIGN=TOP>" );
				    file = new File ( folder, filenames[i] );
				    BufferedReader input = new BufferedReader( new FileReader( file ) );
				    String topline = input.readLine();
				    if ( topline==null || !topline.startsWith( "/*" ) )
				        {
				        out.println( "No information available on stylesheet." );
				        }
				    else
				        {
				        int a=2;
				        int b=topline.indexOf( "*/" );
    				    
				        if ( b == -1 )
				            b = topline.length();
    				        
			            out.print( topline.substring( a, b ) );

				        while ( b == topline.length() )
				            {
				            topline = input.readLine();
				            a=0;
				            b=topline.indexOf( "*/" );
				            if ( b == -1 )
				                b = topline.length();
				            out.print( topline.substring( a, b ) );
				            }
                        }
                        
				    input.close();

				    out.print( "<P><I>View <A TARGET=_new HREF=bs_template_samplehtml" );
				    out.print( filenames[i].substring( 0, filenames[i].indexOf( ".css" ) ) );
				    out.print( ".html>sample text</A></I></P>" );
				    
				    out.println( "</TD></TR>" );
				    }
				
				out.println( "<TR><TD COLSPAN=2 VALIGN=TOP ALIGN=CENTER><INPUT TYPE=SUBMIT VALUE=\"Save Selection\">" );
				out.println( "</TD></TR></TABLE></FORM>" );
				
				}
			}
		catch ( Exception ex )
			{
			logException( out, "PasswordFacility", "stylesheetform", 
			    "There was a problem displaying the form.",
			    ex );
			return;
			}
		}


	private void confirmpreferences( Request req, PrintWriter out )
		throws IOException
		{
		String pname;
		User user;
		PassPhrase pass;
		
		try
			{
			pname=req.getParameter( "preference" );
			
			if ( out==null || pname==null || pname.length()==0 )
			    return;
			    
			user = (User)BuildingContext.getContext().getUser();
			if ( user == null )
				{
				out.println( "<I>Data not available</I>" );
				return;
				}
			
		    
			
			
			if ( pname.equalsIgnoreCase( "interface" ) )
				{
				String intf=req.getParameter( "interface" );

				Metadatum m = Metadatum.findMetadatumByIdAndName( user.getUserId(), "preference.interface" );
				
				
				if ( intf != null && intf.equalsIgnoreCase( "narrative" ) )
				    {
				    if ( m==null )
				        {
				        m=new Metadatum();
				        m.setObjectId( user.getUserId() );
				        m.setName( "preference.interface" );
				        }
				    m.setValue( "narrative" );
				    m.save();
				    }
				else
				    {
				    if ( m!=null )
				        {
				        m.setValue( "graphical" );
				        m.save();
				        }
				    }

				    
				
				out.println( "Interface preference saved." );
				
				return;
				}

			if ( pname.equalsIgnoreCase( "stylesheet" ) )
				{
				String stylefilename=req.getParameter( "stylesheet" );
				File file = new File ( BuildingContext.getProperty( "buildingservlet.templatedirectory" ) );
				file = new File( file, "style_default" + File.separator + "default" + File.separator +  stylefilename );
				
				if ( !file.exists() )
				    {
				    out.println( "<P><B>Can't save preference: Unknown stylesheet file.</B></P>" );
				    return;
				    }

				Metadatum m = Metadatum.findMetadatumByIdAndName( user.getUserId(), "preference.stylesheet" );
				if ( m==null )
				    {
				    m=new Metadatum();
				    m.setObjectId( user.getUserId() );
				    m.setName( "preference.stylesheet" );
				    }
				    
				m.setValue( stylefilename );
				m.save();
				
                                org.bodington.servlet.HttpSession http_session;
                                http_session = (org.bodington.servlet.HttpSession)req.getSession( false );
                                if ( http_session != null )
                                    http_session.removeAttribute( "org.bodington.user_style_sheet" );

                                
				out.println( "Stylesheet preference saved." );
				
				return;
				}

			out.println( "<I>Unknown data item</I>" );
			}
		catch ( Exception ex )
			{
			logException( out, "PasswordFacility", "confirmpreferences", 
			    "There was a problem finding your preferences.",
			    ex );
			return;
			}
		}
    
    public boolean isSysadmin()
    {
        return true;
    }


	}

