#!/usr/bin/perl
############################################################################
#
#   Copyright 1999-2000 Phone.com, Inc.  All rights reserved.
#
#   Subject to the terms and conditions of the SDK License Agreement, 
#   Phone.com, Inc. hereby grants you the right to use the UP.SDK 
#   software and its related documentation.
#
#   The Phone.com name and logo and the family of terms carrying the "UP."
#   prefix are trademarks of Phone.com, Inc. All other brands and product 
#   names may be trademarks of the respective companies with which they 
#   are associated.
#
############################################################################

######################################################################
#
# Clock - WML
#
# This is a simple application that demonstrates displaying time
# in different timezones by calling the UP.Link Settings service to
# get the user's local timezone preference. 
#
# Key concepts illustrated include:
#	- Calling the UP.Link Settings service to retrieve
#	  the user's time zone preference
# 
######################################################################

######################################################################
#
# SDK SAMPLE APPLICATION CONFIGURATION
#
# To configure this application to run on your system:
#
# 1. On Unix, change the first line of the file to use the 
#    path for the Perl interpreter on your system
#
# 2. On NT, verify that the .cgi file extension is mapped to
#    the Perl interpreter on your system or rename the file
#    extension to the default extension that is mapped to the
#    Perl interpreter on your system (e.g. .pl)
#
######################################################################

######################################################################
# AppUtils Loading and Configuration
######################################################################
# Include the apputils directory which has all the SDK utilities
BEGIN { push (@INC, "../apputils");	} # Path to SDK apputils

# Load required application utilities
require Digest;

######################################################################
# Constants
######################################################################
# WML Cards

# This home deck allows the user to select a timezone to view current time.
# It uses a spawn task to retrieve the user's timezone preference from the
# UP.Link Settings (aka Preferences) service (device:home/pref).
$HOMEDECK = '
<wml>
   <card title="Clock">
      <do type="accept">
         <go href="?TZ=$(timezone)"/>
      </do>
      <p>
         <select name="timezone">
            <option>
               <onevent type="onpick">
                  <spawn href="device:home/pref?get=TZ" onexit="?TZ=$(TZ)">
                     <receive/>
                     <receive name="TZ"/>
                  </spawn>
               </onevent>
               Local Time
            </option>
            <option value="A">Pacific</option>
            <option value="B">Mountain</option>
            <option value="C">Central</option>
            <option value="D">Eastern</option>
         </select>
      </p>
   </card>
</wml>';

# This deck displays the time for the selected time zone.
#
# NOTE:  UP.Browser will not reload the current deck unless 
#	 a Content-location string is returned (in the digest), and it 
#	 thinks the deck being requested has a different URL than the 
#	 current deck.  We do this by including an invalid argument value 
#	 ("dummy=foo") in the URL so the requested URL will never match 
#	 the one in the history.  This problem exists only when you're 
#	 trying to reload a card in the current deck, otherwise TTL=0 
#	 should be respected.
$ZONEDECK = '
<wml>
   <card title="%s">
      <onevent type="ontimer">
         <go href="?TZ=%s&amp;dummy=foo"/>
      </onevent>
      <timer name="timerVar" value="600"/>
      <do type="options" label="Sync">
         <go href="?TZ=%s&amp;dummy=foo"/>
      </do>
      <p>%s</p>
      <p align="center">%s</p>
   </card>
</wml>';


# Zone lookup table (US Daylight Savings Times)
#
# 	Format:  "<zone_key>","<zone>|<time_offset>"
#
%zones =  (	"A","Pacific time|-7",
		"B","Mountain time|-6",
		"C","Central time|-5",
		"D","Eastern time|-4");


######################################################################
#
# MAIN Function
#
###################################################################### 
# Get all our http arguments into cgiVars
%cgiVars = &AppUtils::ParseCGIVars();
 
# Get the timezone variable.
$zone_key   = $cgiVars{"TZ"};

# If the timezone is specified, display the deck with the current time in
# the selected timezone. Otherwise display the home deck allowing the user
# to select a time zone.
#
if (defined($zone_key))
{
	if ($zone_key =~ m/^GMT/) {
 
        	# If zone_key comes from the Settings service, it will start with GMT
	        # and be something like GMT-8GMT-7 (for US Pacific).  The first
	        # offset string (GMT-8) is mandatory.  The second offset string (GMT-7)
	        # is optional and specifies the offset to use for daylight savings time.
	        #
	        ($offset, $optionalDSToffsetString) = $zone_key =~ m/^GMT(-*\d+)(.*)/;
	        $offset = &applyDaylightSavings($offset, $optionalDSToffsetString);
	        $zone = "Local time";
	}
	else {
 
        	# Lookup the zone name and offset from the assoc array
	        #
		($zone, $offset) = split(/\|/,$zones{$zone_key});
	}
 
	# Find the time in the selected time zone.
	# $offset is the time offset in hours from GMT
	#
	$local_time = &getLocalTime($offset);
 
	$deck = sprintf($ZONEDECK, $zone, $zone_key, $zone_key, $zone, $local_time);
 
	my $digest;
	$digest = new Digest;
 
	# Output the deck as a digest, only so we can set the Content-location
	# string.
    	#
		$deckid = sprintf("?TZ=%s", $zone_key);
		$digest->addDeck($deckid, $deck);
    		&AppUtils::OutputDigest($digest->asString());
	}
else {
	&AppUtils::OutputDeck($HOMEDECK);
}
        
######################################################################
# 
# getLocalTime
#
# Calculate localtime as GMT plus some time zone offset.
#
# ARGS
#    $offset    Time zone offset
#
# RETURNS
#    string		Local time (e.g. "12:00pm")
#
###################################################################### 
sub getLocalTime
{
    my($offset) = @_;

    # Add offset to the current time (in seconds)
    #
    $now = time + ($offset * 60 * 60);

    # Translate to GMT time and get time component strings
    #
    ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst)
        = gmtime($now);

    # Use $hour for 24 hour clock or $hour12 for 12 hour clock
    #
    $ampm = ($hour > 11) ? ' pm' : ' am';
    $hour12 = ($hour > 12) ? $hour - 12 : $hour;
    $hour = 12 if ($hour == 0);
    $hour12 = 12 if ($hour12 == 0);
 
    # Build the complete time string
    #
    sprintf("%d:%02d%s", $hour12, $min, $ampm);
}

######################################################################
# 
# applyDaylightSavings
#
# Returns the local time offset based on whether or not daylight savings 
# is in effect.  For the sake of simplicity, this example code applies 
# the daylight savings rule based on the current system clock setting
# (isdst variable).
#
# ARGS
#	$offset 	   	Timezone offset (e.g. -8) 
#	$DSToffsetString   	Timezone offset string for DST (e.g. GMT-7)
#
# RETURNS
#	Timezone offset from GMT to use for local time
#
###################################################################### 
sub applyDaylightSavings
{
    my($offset, $DSToffsetString) = @_;

    # If there is no daylight savings offset specified, just use the 
    # standard offset.
    #
    my ($DSToffset);
    ($DSToffset) = $DSToffsetString =~ m/^GMT(-*\d+)/;
    if ($DSToffset eq '') {
	return $offset;
    }

    # Check the local time to see if the system clock is set to DST.
    # The "isdst" variable will be true if this is the case.
    #
    ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst)
        = localtime(time);

    if ($isdst) {
	return $DSToffset;	
    }
    else {
	return $offset;	
    }
}
