# HDMLDeck.pm - The Class that provides a HDMLDeck Object
# Created by James Pattie, 12/21/2000.

# Copyright (c) 2000 PC & Web Xperience, Inc. http://www.pcxperience.com/
# All rights reserved.  This program is free software; you can redistribute it
# and/or modify it under the same terms as Perl itself.

package HTMLObject::HDMLDeck;
use strict;
use HTMLObject::HDMLCard;
use vars qw($AUTOLOAD $VERSION @ISA @EXPORT);

require Exporter;

@ISA = qw(Exporter AutoLoader);
@EXPORT = qw();
	
$VERSION = '2.30';

# new 
# instantiates an instance of a HDMLDeck Object
# requires: id, version
# optional: ttl, markable, public, accessdomain, accesspath, digestURL
sub new
{
  my $that = shift;
  my $class = ref($that) || $that;
  my $self = bless {}, $class;
  my %args = ( id => "deck0", version => "3.0", ttl => "", markable => "false", public => "false", accessdomain => "", accesspath => "/", digestURL => "", @_ );
  my $errStr = "HTMLObject::HDMLDeck->new() - Error!<br>\n";
  
  $self->{id} = $args{id};
  $self->{version} = $args{version};
  $self->{ttl} = $args{ttl};
  $self->{markable} = $args{markable};
  $self->{public} = $args{public};
  $self->{accessdomain} = $args{accessdomain};
  $self->{accesspath} = $args{accesspath};
  $self->{digestURL} = $args{digestURL};
  
  $self->{cards} = {};
  $self->{cardsOrder} = [];
  $self->{currentCard} = "";

  # do validation
  $self->{error} = !$self->isValid;  
  if ($self->{error})
  {
    $self->{errorString} = $errStr . $self->{errorString};
  }

  return $self;
}

# isValid - Returns 0 or 1 to indicate if the object is valid.
sub isValid
{
  my $self = shift;
  my $error = 0;
  my $errorString = "";
  my $errStr = "HTMLObject::HDMLDeck->isValid() - Error!<br>\n";

  # do validation code here.
  if (length $self->{id} == 0)
  {
    $error = 1;
    $errorString .= "id = '$self->{id}' is invalid!<br>\n";
  }
  if ($self->{version} ne "3.0")
  {
    $error = 1;
    $errorString = "version = '$self->{version}' is invalid!<br>\n";
  }
  if ($self->{markable} !~ /^(true|false)$/)
  {
    $error = 1;
    $errorString = "markable = '$self->{markable}' is invalid!<br>\n";
  }
  if ($self->{public} !~ /^(true|false)$/)
  {
    $error = 1;
    $errorString = "public = '$self->{public}' is invalid!<br>\n";
  }
  if (length $self->{ttl} > 0 && $self->{ttl} !~ /^\d+$/)
  {
    $error = 1;
    $errorString = "ttl = '$self->{ttl}' is invalid!<br>\n";
  }

  $self->{error} = $error;
  $self->{errorString} = $errStr if $error;
  $self->{errorString} .= $errorString;

  return !$error;
}

sub DESTROY
{
  my $self = shift;
}

sub AUTOLOAD
{
  my $self = shift;
  my $type = ref($self) || die "$self is not an object";
  my $name = $AUTOLOAD;
  $name =~ s/.*://;	# strip fully-qualified portion
  unless (exists $self->{$name})
  {
    die "Can't access `$name' field in object of class $type";
  }
  if (@_)
  {
    return $self->{$name} = shift;
  }
  else
  {
    return $self->{$name};
  }
}

# setError
# requires: errorString
# returns: nothing
sub setError
{
  my $self = shift;
  my %args = ( errorString => "", @_ );
  my $errorString = $args{errorString};
  
  $self->{errorString} = $errorString;
  $self->{error} = 1;
}

# didErrorOccur
# returns the value of error.
sub didErrorOccur
{
  my $self = shift;

  return $self->{error};
}

# errorMessage
# returns the value of errorString
sub errorMessage
{
  my $self = shift;
  
  return $self->{errorString};
}

# createCard
# requires: cardType, id
# optional: attributes needed by the specific cardType
# returns: 1=OK, 0=Error, -1=Card already exists
sub createCard
{
  my $self = shift;
  my %args = ( cardType => "display", id => "card0", @_ );
  my $cardType = $args{cardType};
  my $id = $args{id};
  my $errStr = "HTMLObject::HDMLDeck->createCard()  - Error!<br>\n";
  
  if ($cardType !~ /^(display|entry|action|choice|nodisplay)$/)
  {
    $self->{error} = 1;
    $self->{errorString} = $errStr . "cardType = '$cardType' is invalid!<br>\n";
    return 0;
  }
  
  if (exists $self->{cards}->{$id})
  {
    return -1;  # already exists!
  }
  
  # create the HDMLCard Object
  my $hdmlCardObj = HTMLObject::HDMLCard->new(%args);  # pass in all arguments we are given and let the HDMLCard Object do the validation.
  if ($hdmlCardObj->didErrorOccur)
  {
    $self->{error} = 1;
    $self->{errorString} = $errStr . $hdmlCardObj->errorMessage;
    return 0;
  }
  
  # insert into the cards hash
  $self->{cards}->{$id} = $hdmlCardObj;
  
  # append this card to the end of the list so I know the order to display them in.
  push @{$self->{cardsOrder}}, $id;
  
  # set the focus to this card
  $self->{currentCard} = $id;
  
  return 1;
}

# setFocus
# takes: card id to set focus to or nothing to just return current card
# returns: card that previously had focus or "" if no previous card
sub setFocus
{
  my $self = shift;
  my $card = shift;
  my $errStr = "HTMLObject::HDMLDeck->setFocus()  - Error!<br>\n";
  my $oldCard = $self->{currentCard};
  
  if (length $card == 0)
  {
    return $oldCard;
  }
  else
  {
    if (!exists $self->{cards}->{$card})
    {
      $self->{error} = 1;
      $self->{errorString} = $errStr . "card = '$card' does not exist!<br>\n";
      return $oldCard;
    }
    $self->{currentCard} = $card;
  }
  
  return $oldCard;
}

# setCardFocus
# takes: location
# returns: previous location
# sets/returns the focus of the currently selected card.  Blows an error if no
# card created.
sub setCardFocus
{
  my $self = shift;
  my $location = shift;
  my $errStr = "HTMLObject::HDMLDeck->setCardFocus()  - Error!<br>\n";
  my $oldLocation = "";
  
  if (length $self->{currentCard} == 0)
  {
    $self->{error} = 1;
    $self->{errorString} = $errStr . "No cards defined!<br>\n";
    return "";
  }
  
  $oldLocation = $self->{cards}->{$self->{currentCard}}->setFocus($location);
  if ($self->{cards}->{$self->{currentCard}}->didErrorOccur)
  {
    $self->{error} = 1;
    $self->{errorString} = $errStr . $self->{cards}->{$self->{currentCard}}->errorMessage;
    return "";
  }
  
  return $oldLocation;
}

# print
# takes: text to place in content of current card
# returns: nothing
sub print
{
  my $self = shift;
  my $content = shift;
  my $errStr = "HTMLObject::HDMLDeck->print()  - Error!<br>\n";
  
  if (length $self->{currentCard} == 0 || !exists $self->{cards}->{$self->{currentCard}})
  {
    $self->{error} = 1;
    $self->{errorString} = $errStr . "'$self->{currentCard}' is invalid!<br>\n";
    return;
  }
  
  # print the content into the card.
  $self->{cards}->{$self->{currentCard}}->print($content);
}

# display
# takes: nothing
# returns: string containing <hdml version="" ...> .. </hdml> output to display
sub display
{
  my $self = shift;
  my $errStr = "HTMLObject::HDMLDeck->display()  - Error!<br>\n";
  my $output = "";
  
  $output .= "<hdml version=$self->{version}";
  $output .= " ttl=$self->{ttl}" if (length $self->{ttl} > 0);
  $output .= " markable=$self->{markable} public=$self->{public}";
  $output .= " accessdomain=$self->{accessdomain}" if (length $self->{accessdomain} > 0 && $self->{public} eq "false");
  $output .= " accesspath=$self->{accesspath}" if (length $self->{accesspath} > 0 && $self->{public} eq "false");
  $output .= ">\n";
  
  foreach my $card (@{$self->{cardsOrder}})
  {
    # print this card into the output stream
    $output .= $self->{cards}->{$card}->display();
    if ($self->{cards}->{$card}->didErrorOccur)
    {
      $self->{error} = 1;
      $self->{errorString} = $errStr . $self->{cards}->{$card}->errorMessage;
      return "";
    }
  }
  
  $output .= "</hdml>\n";
  
  return $output;
}

1;
__END__

=head1 NAME

HDMLDeck - Object used to build a HDMLDeck Object Class.

=head1 SYNOPSIS

  use HTMLObject::HDMLDeck;
  my $obj = HTMLObject::HDMLDeck->new;
  if ($obj->didErrorOccur())
  {
    die $obj->errorMessage();
  }

=head1 DESCRIPTION

HDMLDeck is a HDMLDeck class.

=head1 Exported FUNCTIONS

  scalar new(version, ttl, markable, public, accessdomain, accesspath)
    Creates a new instance of the HTMLObject::HDMLDeck
    object.  version is the only required value and must = "3.0".

  bool isValid(void)
    Returns 0 or 1 to indicate if the object is valid.  The error will 
    be available via errorMessage().

  void setError(errorString)
    sets error and errorString to indicate an error occurred.

  scalar didErrorOccur(void)
    Returns the value of error.

  scalar errorMessage(void)
    Returns the value of errorString.
    
  int createCard(cardType, id, arguments for card)
    Creates a new HDMLCard Object and stores it in the cards hash under
    the id value.  The focus is automatically set to this new card 
    until changed by the user.  Returns -1 if the card already exists.
    
  scalar setFocus(scalar)
    This sets the focus to the new card id and returns the old card id
    that previously had the focus.  If no card was previously created it
    will return an empty string.  If no value is given, then it just
    returns the card that has the focus.
    
  scalar setCardFocus(scalar)
    Sets the focus of the currently selected card to the specified 
    location and returns the old focus.
    
  void print(scalar)
    Prints the contents of the string passed in to the card that 
    currently has the focus.  If no card is defined, then we blow an
    error.
    
  scalar display(void)
    Returns the <hdml version="" ...>...</hdml> string that represents 
    the contents of this HDMLDeck Object.
    

  NOTE:  All data fields are accessible by specifying the object
         and pointing to the data member to be modified on the
         left-hand side of the assignment.
         Ex.  $obj->variable($newValue); or $value = $obj->variable;

=head1 AUTHOR

James A. Pattie (mailto:htmlobject@pcxperience.com)

=head1 SEE ALSO

perl(1), HTMLObject::WAP(3)

=cut
