#!/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.
#
############################################################################

######################################################################
#
# Acme Employee Directory - HTML
#
# The application allows a user to browse the employee directory and edit
# entries. This HTML version of the employee directory is shown to
# demonstrate access to the same information (employee directory in
# this case) from a traditional HTML interface and from the phone.
#
# Application Flow:
#
# A user's navigation through the application is represented as state
# machine transitions.  Each URL encodes the state to transition to in
# the "NEXT" (Next State) argument.  The main routine of the application
# examines the NEXT argument, calls a routine to perform the appropriate 
# action and to output the next page.
#
# The NEXT state could be one of the following:
# Disp or blank - To display the employee directory
# Edit - To display the edit form with values from the selected entry
# Update - To update the entry and display the updated list
# Add - To display a blank form to create a new entry
# Submit - To add the new entry to the database and display the updated list
# Delete - To delete the selected entry and display the updated list
#
######################################################################

######################################################################
#
# 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)
#
# 3. Make sure that the employees.data file is writable by the process
#    running the HTTP request (usually user 'nobody' on Unix).
#
# 4. [Optional] Change the $TITLE variable below to change the title 
#    of the display
#
# 5. [Optional] Place an image (e.g. company logo) in amce.gif in the current
#    directory to be displayed at the top left of the employee listing
#
######################################################################

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

require 'FileUtils.pl';
require 'DeckUtils.pl';

######################################################################
# Constants
######################################################################
# The phone list data file
$phoneFileName = './employees.data';

#Change the following to change the title of the display
$TITLE = "Acme Employee Directory";

######################################################################
# State definitions
#
# main uses these definitions to determine next state
######################################################################
%FunctionArray = (
                   "Disp", "displayPhoneList",
                   "Edit", "editEntry",
                   "Update", "submitEdit",
                   "Delete", "deleteEntry",
                   "Add", "addEntry",
                   "Submit", "submitAdd"
                 );

#Call the main function to begin execution
&main();

######################################################################
#
# main Function
#
# When a URL request is received, the application checks the value of 
# NEXT to determine the next action.
#
# This function also reads the CGI variables into %cgiVars for the
# rest of the application to use
#
###################################################################### 
sub main
{
	my($commandKey, $subRoutine);

	# Get any arguments we were passed
	%cgiVars = &AppUtils::ParseCGIVars();

	# Invoke the appropriate function
	$commandKey = $cgiVars{"NEXT"};
	$commandKey = "Disp" if (!$commandKey);

	# Find the function to execute for the NEXT state
	# Display the home page if unknown state
	$subRoutine = $FunctionArray{$commandKey};
	if ($subRoutine) {
		&$subRoutine();
	}
	else {
		&displayPhoneList();
	}
}

######################################################################
# displayPhoneList
#
# This function displays the employee directory as a HTML table.
# The table provides a radio box to allow the user to select an entry.
# The page also provides buttons to "Add", "Edit" or "Delete" an entry
# 
######################################################################
sub displayPhoneList
{
	my($status, $title, $body);
	my($last, $first, $office, $homePhone, $homeType);
	my($altPhone, $altType, $email, $homepage);
	my($name);

	# Open the phonelist file
	&AppUtils::OpenWithLock(\*PHONE_DATA, "<$phoneFileName", 'READ');

	#If there is a logo.gif, display it in the top left.
	if (-e "../images/acme.gif") {
		$body .= "<IMG SRC=\"../images/acme.gif\" BORDER=0 ALT=\"[ Company logo here ]\">";
        }

	# Center the body and start the table
	$body .= "<CENTER>\n";
	$body .= "<H1>$TITLE</H1>\n";
	$body .= "<FORM method=GET action=\"acme_html.cgi\">\n";
	$body .= "<TABLE BORDER>\n";
	$body .= "<TR><TH>Select<TH>Name<TH>Phone<TH>Fax<TH>EMail</TR>\n\n";

	# Add the names to the table
	while(<PHONE_DATA>) {

		chop; #Remove the \n in each line

		# skip any comment lines or blank lines
		next if (m/^\s*\#/);
		next if (m/^\s*$/);

		#The fields are delimited by | in the input file
		($last, $first, $office, $fax, $email) = split('\|');

		$body .= "<TR>\n";
		$body .= "  <TD><INPUT type=radio name=key value=\'$email$office'></TD>\n";
		$name = $first if($first && !$last);
		$name = $last if(!$first && $last);
		$name = sprintf("$last, $first") if($first && $last);
				
		$body .= "  <TD>$name</TD>\n";
		$body .= "  <TD>$office</TD>\n";
		$body .= "  <TD>$fax</TD>\n";
		$body .= "  <TD><A href=\"mailto:$email\">$email</A></TD>\n";
		$body .= "</TR>\n\n";
	}

	&AppUtils::CloseWithLock(\*PHONE_DATA);

	# End the table
	$body .= "</TABLE>\n";
	$body .= "<p>Select Entry, then select action (as desired)";
	$body .= "<p><INPUT type=submit name=NEXT value=\"Edit\">\n";
	$body .= "<INPUT type=submit name=NEXT value=\"Delete\">\n";
	$body .= "<INPUT type=submit name=NEXT value=\"Add\">\n";
	$body .= "</FORM>\n";
	$body .= "</CENTER>\n";

	&outputHTML($title, $body);
}

######################################################################
# editEntry
#
# This function calls displayEntryForm to display a form to allow the user
# to edit the selected entry. This function fills in the form fields with
# values from the selected entry.
# 
######################################################################
sub editEntry
{
	my($editKey) = $cgiVars{"key"};
	my($title);
	my($last, $first, $office, $fax, $email);
	my($regularSelect, $homeSelect, $cellSelect, $pageSelect, $unreliableSelect);
	my($found);
	my($status);

	# Open up the phonelist file
	&AppUtils::OpenWithLock(\*PHONE_DATA, "<$phoneFileName", 'READ');

	# Find the entry we are editing
	$found = 0;
	while(<PHONE_DATA>) {

		chop;

		# skip any comment lines or blank lines
		next if (m/^\s*\#/);
		next if (m/^\s*$/);

		($last, $first, $office, $fax, $email) = split('\|');

		if ($editKey eq "$email$office") {
			$found = 1;
			last;
		}
	}

	&AppUtils::CloseWithLock(PHONE_DATA);

	if ($found) {
		$title = "Edit Entry";
		$body = &displayEntryForm($title, "Update", $editKey, 
                                          $last, $first, $office, 
                                          $fax, $email);
	}
	else {
		$title = "Error";
		$body = "Could not find entry to edit.";
	}

	&outputHTML($title, $body);
}

######################################################################
# submitEdit
#
# This function is called when the user edits an existing entry with the form
# displayed by the editEntry function shown above. This function updates
# the employee data file and displays the updated employee list
# 
######################################################################
sub submitEdit
{
	my($editKey) = $cgiVars{"key"};
	my($newLast) = $cgiVars{"last"};
	my($newFirst) = $cgiVars{"first"};
	my($newOff) = $cgiVars{"newOff"};
	my($newFax) = $cgiVars{"fax"};
	my($newEmail) = $cgiVars{"email"};
	my($last, $first, $office, $fax, $email);
	my($title, $body);
	my($found);
	my(@fileData);
	my(@names);
	my($status);

	# Open up the phonelist file
	&AppUtils::OpenWithLock(\*PHONE_DATA, "+<$phoneFileName", 'WRITE');

	# Find the entry we are deleting
	$found = 0;
	while(<PHONE_DATA>) {
			
		chop;

		# skip any comment lines or blank lines
		if (/^\s*\#/ || /^\s*$/) {
			push(@fileData, "$_\n");
			next;
		}

		($last, $first, $office, $fax, $email) = split('\|');

		if ($editKey eq "$email$office") {
			$found = 1;
			push(@names, 
			"$newLast\|$newFirst\|$newOff\|$newFax\|$newEmail\n");
		}
		else {
			push(@names, "$_\n");
		}
	}

	if ($found) {
		# Clear out the old data
		truncate(PHONE_DATA, 0);
		seek(PHONE_DATA, 0, 0);

		# Write the new data
		print PHONE_DATA @fileData;
		print PHONE_DATA sort @names;

		&AppUtils::CloseWithLock(\*PHONE_DATA);

		&displayPhoneList();
		return;
	}
	else {
		$title = "Error";
		$body = "Could not find entry with phone $office";
	}

	&outputHTML($title, $body);
}

######################################################################
# displayEntryForm
#
# This function is used by editEntry and addEntry to display a HTML form
# to allow the user to specify details for an employee record.
# 
######################################################################
sub displayEntryForm
{
	my($title, $nextState, $editKey, $last, $first, $office, $fax, $email)=@_;
	my($body);

	$body .= "<H1>$title</H1>\n";
	$body .= "<FORM method=GET action=\"acme_html.cgi\">\n";
	if($editKey) {
		$body .= "<input type=hidden name=key value=\'$editKey\'>\n";
	}
	$body .= "<TABLE>\n";

	$body .= "<TR>\n";
	$body .= "<TD align=right>First name:</TD>\n";
	$body .= "<TD><INPUT size=30 name=first value=\"$first\"></TD>\n";
	$body .= "</TR>\n";

	$body .= "<TR>\n";
	$body .= "<TD align=right>Last name:</TD>\n";
	$body .= "<TD><INPUT size=30 name=last value=\"$last\"></TD>\n";
	$body .= "</TR>\n";

	$body .= "<TR>\n";
	$body .= "<TD align=right>Phone:</TD>\n";
	$body .= "<TD><INPUT size=15 name=newOff value=\"$office\"></TD>\n";
	$body .= "</TR>\n";

	$body .= "<TR>\n";
	$body .= "<TD align=right>Fax:</TD>\n";
	$body .= "<TD><INPUT size=15 name=fax value=\"$fax\"></TD>\n";
	$body .= "</TR>\n";

	$body .= "<TR>\n";
	$body .= "<TD align=right>Email:</TD>\n";
	$body .= "<TD><INPUT size=30 name=email value=\"$email\"></TD>\n";
	$body .= "</TR>\n";

	$body .= "</TABLE>\n";
	$body .= "<INPUT type=submit name=NEXT value=$nextState>\n";
	$body .= "</FORM>\n";

	return $body;
}

######################################################################
# addEntry
#
# This function is called if the user selects "Add" from the employee
# directory listing page to create an new employee entry. It uses 
# displayEntryForm to present a HTML form for input
# 
######################################################################
sub addEntry
{
	my($title, $body);
	
	$title = "Add Entry";
	$body = &displayEntryForm($title, "Submit");

	&outputHTML($title, $body);
}

######################################################################
# submitAdd
#
# This function is called when the user fills in the "Add' form to add
# a new employee entry to the directory.  This function updates the
# employees data file then displays the updated list
# 
######################################################################
sub submitAdd
{
	my($newLast) = $cgiVars{"last"};
	my($newFirst) = $cgiVars{"first"};
	my($newOff) = $cgiVars{"newOff"};
	my($newFax) = $cgiVars{"fax"};
	my($newEmail) = $cgiVars{"email"};
	my($last, $first, $office, $fax, $email);
	my($title, $body);
	my($found);
	my(@fileData);
	my(@names);
	my($status);

	# Open up the phonelist file
	&AppUtils::OpenWithLock(\*PHONE_DATA, "+<$phoneFileName", 'WRITE');

	# read in the old file
	while(<PHONE_DATA>) {
		
		chop;

		# skip any comment lines or blank lines
		if (/^\s*\#/ || /^\s*$/) {
			push(@fileData, "$_\n");
			next;
		}

		push(@names, "$_\n");
	}
		
	# add the new name
	push(@names, "$newLast\|$newFirst\|$newOff\|$newFax\|$newEmail\n");
	
	# Clear out the old data
	truncate(PHONE_DATA, 0);
	seek(PHONE_DATA, 0, 0);

	# Write the new data
	print PHONE_DATA @fileData;
	print PHONE_DATA sort @names;

	&AppUtils::CloseWithLock(\*PHONE_DATA);
		
	&displayPhoneList();
	return;

	&outputHTML($title, $body);
}

######################################################################
# deleteEntry
#
# This function is called when the user selects an entry from the
# employee listing and clicks on "Delete" to remove the entry.
# This function deletes the selected entry from the employees data 
# file then displays the updated list
# 
######################################################################
sub deleteEntry
{
	my($editKey) = $cgiVars{"key"};
	my($last, $first, $office, $fax, $email);
	my($title, $body);
	my($found);
	my(@fileData);
	my($status);

	# Open up the phonelist file
	&AppUtils::OpenWithLock(\*PHONE_DATA, "+<$phoneFileName", 'WRITE');

	# Find the entry we are deleting
	$found = 0;
	while(<PHONE_DATA>) {
			
		chop;

		# skip any comment lines or blank lines
		if (/^\s*\#/ || /^\s*$/) {
			push(@fileData, "$_\n");
			next;
		}

		($last, $first, $office, $fax, $email) = split('\|');

		if ($editKey eq "$email$office") {
			$found = 1;
		}
		else {
			push(@fileData, "$_\n");
		}
	}

	if ($found) {
		# Clear out the old data
		truncate(PHONE_DATA, 0);
		seek(PHONE_DATA, 0, 0);

		# Write the new data
		print PHONE_DATA @fileData;

		&AppUtils::CloseWithLock(\*PHONE_DATA);

		&displayPhoneList();
		return;
	}
	else {
		$title = "Error";
		$body = "Could not find entry to delete";
	}

	&outputHTML($title, $body);
}

######################################################################
#
# outputHTML
#
# Generic function used to output HTML with appropriate HTTP headers.
# Argments: HTML title, HTML body
#
######################################################################
sub outputHTML
{
	my($title, $body) = @_;

	print "HTTP/1.0 200 OK" if ($ENV{'PERLXS'} eq 'PerlIS');
	print sprintf("Content-type: text/html%c%c", 10, 10);

	print "<HTML>\n";
	print "<HEAD>\n";
	print "<TITLE>$title</TITLE>\n";
	print "</HEAD>\n";
	print "<BODY>\n";
	print "$body";
	print "</BODY>\n";
	print "</HTML>\n";
}

