import java.util.*;
import java.text.*;

import javax.servlet.*;
import com.oroinc.text.perl.*;

/**
 * This class provides a way to get useful information about a client
 * connecting via a URL.  It can be used by other classes that want
 * to tailor time/date or language output depending on where the user
 * is coming from.
 **/
public class ClientInfo {

    private static Perl5Util regex       = new Perl5Util();
    private static Hashtable localeTable = makeLocaleTable();

    /*
     * Strings to use for building SimpleDateFormats
     */
    private static final String US_WITH_TIME = "MMMMM d, h:mm aa, z";
    private static final String US_NO_TIME   = "MMMMM d";
    private static final String EU_WITH_TIME = "d. MMMMM, H:mm";
    private static final String EU_NO_TIME   = "d. MMMMM";

    /**
     * Info variables with default values.
     **/
    private Locale myLocale = Locale.US;
    

    /**
     * Construct a ClientInfo instance that derives its information from
     * given hostname.
     **/
    public ClientInfo(String hostname) {
	init(hostname);
    }


    /**
     * Construct a ClientInfo instance that derives its information from
     * given servlet request.
     **/
    public ClientInfo(ServletRequest request) {
	init(request.getRemoteHost());
    }


    /**
     * Initialize
     **/
    private void init(String hostname) {
	Locale l;
	String tld;

	/*
	 * 1. Parse out the TLD
	 */
	if (hostname == null) return;
	hostname = hostname.toLowerCase();
	if (! regex.match("/.+\\.([a-z][a-z][a-z]?)$/", hostname)) return;
	tld = regex.group(1);
	
	/*
	 * 2. Try to find it in the table.
	 */
	l = (Locale) localeTable.get(tld);
	if (l != null) myLocale = l;
    }


    /**
     * Create a hash table that maps Top Level Domains to country
     * locales.
     **/
    private static Hashtable makeLocaleTable() {
	Hashtable table = new Hashtable();

	table.put("com", Locale.US);
	table.put("org", Locale.US);
	table.put("net", Locale.US);
	table.put("gov", Locale.US);
	table.put("edu", Locale.US);

	table.put("ca", Locale.CANADA);
	table.put("cn", Locale.CHINA);
	table.put("fr", Locale.FRANCE);
	table.put("de", Locale.GERMANY);
	table.put("it", Locale.ITALY);
	table.put("jp", Locale.JAPAN);
	table.put("kr", Locale.KOREA);
	table.put("tw", Locale.TAIWAN);
	table.put("uk", Locale.UK);
	table.put("us", Locale.US);

	return table;
    }



    /*
     * A C C E S S O R S
     */


    /**
     * Return the client's locale.
     **/
    public Locale getLocale() {
	return myLocale;
    }


    /**
     * Return a date format appropriate for my locale, that includes
     * the time.
     **/
    public SimpleDateFormat getFormatWithTime() {
	if (myLocale == Locale.US)
	    return new SimpleDateFormat( US_WITH_TIME, myLocale );
	else
	    return new SimpleDateFormat( EU_WITH_TIME, myLocale );
    }


    /**
     * Return a date format appropriate for the locale, that does not
     * include the time.
     **/
    public SimpleDateFormat getFormatWithoutTime() {
	if (myLocale == Locale.US)
	    return new SimpleDateFormat( US_NO_TIME, myLocale );
	else
	    return new SimpleDateFormat( EU_NO_TIME, myLocale );
    }



    /*
     * S T A N D A R D   M E T H O D S
     */

    /**
     * Return a string representation of myself.
     **/
    public String toString() {
	return "ClientInfo( "+myLocale+" )";
    }
}
