/*
 * Created on 20-Jan-2005
 */
package org.bodington.servlet.facilities;

import java.awt.Color;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Calendar;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.logging.Logger;

import org.bodington.server.BuildingServer;
import org.bodington.server.BuildingServerException;
import org.bodington.servlet.Request;


/**
 * @author buckett
 */
public class Utils
{
    
    private static Logger log = Logger.getLogger(Utils.class.getName());

    private static final Map days = new TreeMap();
    private static final Map hours = new TreeMap();
    private static final Map minutes = new TreeMap();
    private static final String[] monthNames = {"January", "Febuary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "Decemeber"};
    private static final Map months = new TreeMap();

    static {
    	for(int count = 0; count < 24; count++) {
    		final Integer hour = new Integer(count);
    		hours.put(hour, hour);
    	}
    	for(int count = 0; count < 60; count++) {
    		final Integer minute = new Integer(count);
    		minutes.put(minute, minute);
    	}
    	for(int count = 1; count< 32; count++) {
    		final Integer day = new Integer(count);
    		days.put(day,day);
    	}
    	for(int count = 0; count < 12; count++) {
    		final Integer month = new Integer(count);
    		months.put(month, monthNames[count]);
    		
    	}
    	
    	
    }

    /**
     * Attempt to convert the calendar data in the request into a calendar object.
     * If the conversion fails then null is returned.
     * @param req The servlets request to get the raw data from.
     * @param prefix The prefix that the form elements used.
     * @return The converted calendar object.
     */
    public static Calendar parseCalendarChooser(Request req, String prefix)
    {
    	Calendar calendar = Calendar.getInstance();
    	try
    {
    		calendar.set(
    			Integer.parseInt(req.getParameter(prefix+ ".year")),
    		Integer.parseInt(req.getParameter(prefix+ ".month")),
    		Integer.parseInt(req.getParameter(prefix+ ".day")),
    		Integer.parseInt(req.getParameter(prefix+ ".hour")),
    		Integer.parseInt(req.getParameter(prefix+ ".minute"))
    		
    		);
    }
    	catch (NumberFormatException nfe)
    {
    		return null;
    }
    	return calendar;
    		
    }

    public static void writeCalendarChooser(PrintWriter out, String prefix)
    {
    	writeCalendarChooser(out, prefix, Calendar.getInstance());
    }

    /**
     * Outputs a date and time chooser to the page. If no default calendar is supplied
     * the currently time/date is used. The really should be in a template which can then
     * be included into other pages so the changing to format of the calendar can be done without
     * having to hack the Java.
     * @param out Where all the HTML is written to.
     * @param prefix The prefix for all the calendar form elements to allow multiple calendars on a page.
     * @param calendar The value to set the calendar chooser to.
     * @see writeSelect()
     */
    public static void writeCalendarChooser(PrintWriter out, String prefix, Calendar calendar)
    {
    	if (calendar == null) {
    		calendar = Calendar.getInstance();
    	}
    	out.write("Time: ");
    	writeSelect(out, prefix+".hour", hours, new Integer(calendar.get(Calendar.HOUR_OF_DAY)));
    writeSelect(out, prefix+".minute", minutes, new Integer(calendar.get(Calendar.MINUTE)));
    	out.write("<br/>");
    	out.write("Date: ");
    	writeSelect(out, prefix+".day", days, new Integer(calendar.get(Calendar.DAY_OF_MONTH)));
    	writeSelect(out, prefix+".month", months, new Integer(calendar.get(Calendar.MONTH)));
    	out.write("<input type=\"text\" name=\""+ prefix + ".year\" value=\""+ calendar.get(Calendar.YEAR)+ "\" size=\"4\"/>");
    	
    }

    /**
     * Outputs an HTML &lt;select&gt; tag with the values supplied. No sensible checking is 
     * done at the moment. The Map supplied to this function probably wants to be a
     *  SortedMap so that the items are displayed in a sensible manner. 
     * @param out Where all the HTML output is written.
     * @param name The name associated with this form element.
     * @param values A Map containing the values to be outputed. 
     * @param selected The key in the Map that should be selected.
     */
    public static void writeSelect (PrintWriter out, String name, Map map, Object selected)
    {
    	out.write("<select name=\""+ name+ "\">\n");
    	Set entries = map.entrySet();
    	Iterator entriesIt = entries.iterator();
    	while (entriesIt.hasNext())
    	{
    		final Map.Entry entry =(Map.Entry)entriesIt.next();
    		out.write("<option value=\""+ entry.getKey() +"\"");
    		if (entry.getKey().equals(selected))
    		{
    			out.write(" selected");
    		}
    		if (entry.getValue() == null) 
    		{
    			out.write("/>\n");
    		}
    		else 
    		{
    			out.write(">"+ entry.getValue()+ "</option>\n");
    		}
    	}
    	// Finish the select
    	out.write("</select>\n");		
    }
    
    /**
     * Check to see if a username should be logging in using WebAuth.
     * @param username The username to check.
     * @return True if the user should be doing WebAuth.
     * @throws BuildingServerException If something went wrong with the check.
     */
    public static boolean checkWebAuthUser(String username) throws BuildingServerException
    {
    	//TODO Maybe we should be using the Jakarta Commons HTTP client as it supports timeouts in a nicer way. 
        HttpURLConnection connection = null;
        BufferedReader in = null;
        String url = null;
        String line = null;
        try
        {
            // Make the timeout small
            // http://java.sun.com/j2se/1.4.2/docs/guide/net/properties.html
            System.setProperty("sun.net.client.defaultConnectTimeout", "5000");
            System.setProperty("sun.net.client.defaultReadTimeout", "10000");
            url = new String(BuildingServer.getInstance().getProperties()
                .getProperty("bodington.webauth.url",
                    "http://admin.herald.ox.ac.uk/weblearn_status")
                + "?username=" + URLEncoder.encode(username, "UTF-8"));
            log.fine("Starting checking: "+ username);
            connection = (HttpURLConnection) new URL(url).openConnection();
            connection.connect();
            if (connection.getResponseCode() != HttpURLConnection.HTTP_OK)
            {
                throw new BuildingServerException("WA check got bad result: "+ connection.getResponseCode());
            }
            in = new BufferedReader(new InputStreamReader(connection
                .getInputStream()));
            while (true)
            {
                line = in.readLine();
                if (line == null)
                {
                    break;
                }
                if (line.startsWith("Status: "))
                {
                    line = line.substring(8);
                    if (line.equals("ok"))
                        return true;
                    else if (line.equals("expired"))
                        return false;
                    else if (line.equals("not found"))
                        return false;
                    else if (line.equals("bad request")) return false;
                }

            }
        }
        catch (MalformedURLException e)
        {
            log.warning("Invalid URL: " + url);
            throw new BuildingServerException(e.toString());
        }
        catch (IOException e)
        {
            log.warning("IO problem");
            throw new BuildingServerException(e.toString());
        }
        finally
        {
            log.fine("Finished checking: "+ username);
            if (in != null)
            {
                try
                {
                    in.close();
                }
                catch (IOException ioe)
                {
                    ;
                }
            }
            if (connection != null)
            {
                connection.disconnect();
            }

        }

        return false;
    }
    
    public static String toCSSColor(Color color)
    {
        return "#"+ Integer.toHexString( color.getRGB() ).substring( 2 );
    }

}
