# HDMLCard.pm - The Class that provides a HDMLCard 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::HDMLCard;
use strict;
use vars qw($AUTOLOAD $VERSION @ISA @EXPORT);

require Exporter;

@ISA = qw(Exporter AutoLoader);
@EXPORT = qw();

$VERSION = '2.30';

# new 
# instantiates an instance of a HDMLCard Object
# requires: cardType, id
# cardType = display 
#  required: name
#  optional: title, markable, bookmark
# cardType = entry
#  required: name, key
#  optional: title, markable, bookmark, format, default, noecho, emptyok
# cardType = action
#  required: type, task
#  optional: label, dest, rel=Next, method (post|get), postdata, acceptCharset, vars, receive, retvals, next, cancel, friend, sendreferer, clear, number, src, icon
# cardType = choice
#  required: name
#  optional: key, title, markable, bookmark, ikey, method, default, idefault
# cardType = nodisplay
#  required: name
#  optional:
sub new
{
  my $that = shift;
  my $class = ref($that) || $that;
  my $self = bless {}, $class;
  my %args = ( cardType => "display", id => "card0", @_ );
  my $errStr = "HTMLObject::HDMLCard->new() - Error!<br>\n";
  my $cardType = $args{cardType};
  my $id = $args{id};
  
  if ($cardType !~ /^(display|entry|action|choice|nodisplay)$/)
  {
    $self->{error} = 1;
    $self->{errorString} = $errStr . "cardType = '$cardType' is invalid!<br>\n";
    return $self;
  }
  if (length $id == 0)
  {
    $self->{error} = 1;
    $self->{errorString} = $errStr . "id = '$id' is invalid!<br>\n";
    return $self;
  }
  
  $self->{cardType} = $cardType;
  $self->{id} = $id;
  
  if ($cardType eq "display")
  {
    $self->{name} = $args{name};
    $self->{title} = $args{title};
    $self->{markable} = $args{markable};
    $self->{bookmark} = $args{bookmark};
  }
  elsif ($cardType eq "entry")
  {
    $self->{name} = $args{name};
    $self->{key} = $args{key};
    $self->{title} = $args{title};
    $self->{markable} = $args{markable};
    $self->{bookmark} = $args{bookmark};
    $self->{format} = $args{format};
    $self->{default} = $args{default};
    $self->{noecho} = $args{noecho};
    $self->{emptyok} = $args{emptyok};
  }
  elsif ($cardType eq "action")
  {
    $self->{label} = $args{label};
    $self->{type} = $args{type};
    $self->{task} = $args{task};
    $self->{dest} = $args{dest};
    $self->{rel} = $args{rel};
    $self->{method} = $args{method};
    $self->{postdata} = $args{postdata};
    $self->{acceptCharset} = $args{acceptCharset};
    $self->{vars} = $args{vars};
    $self->{receive} = $args{receive};
    $self->{retvals} = $args{retvals};
    $self->{next} = $args{next};
    $self->{cancel} = $args{cancel};
    $self->{friend} = $args{friend};
    $self->{sendreferer} = $args{sendreferer};
    $self->{clear} = $args{clear};
    $self->{number} = $args{number};
    $self->{src} = $args{src};
    $self->{icon} = $args{icon};
  }
  elsif ($cardType eq "choice")
  {
    $self->{name} = $args{name};
    $self->{key} = $args{key};
    $self->{title} = $args{title};
    $self->{markable} = $args{markable};
    $self->{bookmark} = $args{bookmark};
    $self->{ikey} = $args{ikey};
    $self->{method} = $args{method};
    $self->{default} = $args{default};
    $self->{idefault} = $args{idefault};
  }
  elsif ($cardType eq "nodisplay")
  {
    $self->{name} = $args{name};
  }

  $self->{actions} = "";  # The actions in this card.  
  $self->{content} = "";  # The content of the card.
  $self->{location} = ($cardType eq "nodisplay" ? "actions" : "content");  # default location.
  
  # 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::HDMLCard->isValid() - Error!<br>\n";

  # do validation code here.
  if ($self->{cardType} eq "display")
  {
    if (length $self->{name} == 0)
    {
      $error = 1;
      $errorString .= "name = '$self->{name}' is invalid!<br>\n";
    }
    if (length $self->{markable} > 0 && $self->{markable} !~ /^(true|false)$/)
    {
      $error = 1;
      $errorString .= "markable = '$self->{markable}' is invalid!<br>\n";
    }
  }
  elsif ($self->{cardType} eq "entry")
  {
    if (length $self->{name} == 0)
    {
      $error = 1;
      $errorString .= "name = '$self->{name}' is invalid!<br>\n";
    }
    if (length $self->{markable} > 0 && $self->{markable} !~ /^(true|false)$/)
    {
      $error = 1;
      $errorString .= "markable = '$self->{markable}' is invalid!<br>\n";
    }
    if (length $self->{key} == 0)
    {
      $error = 1;
      $errorString .= "key = '$self->{key}' is invalid!<br>\n";
    }
    if (length $self->{noecho} > 0 && $self->{noecho} !~ /^(true|false)$/)
    {
      $error = 1;
      $errorString .= "noecho = '$self->{noecho}' is invalid!<br>\n";
    }
    if (length $self->{emptyok} > 0 && $self->{emptyok} !~ /^(true|false)$/)
    {
      $error = 1;
      $errorString .= "emptyok = '$self->{emptyok}' is invalid!<br>\n";
    }
  }
  elsif ($self->{cardType} eq "action")
  {
    if ($self->{type} !~ /^(accept|help|prev|soft1|soft2|send|delete)$/)
    {
      $error = 1;
      $errorString .= "type = '$self->{type}' is invalid!<br>\n";
    }
    if ($self->{type} =~ /^(help|soft1|soft2|send|delete)$/)
    {
      if (length $self->{label} == 0 || length $self->{label} > 5)
      {
        $error = 1;
        $errorString .= "label = '$self->{label}' is invalid!<br>\n";
      }
    }
    elsif ($self->{type} eq "accept")
    {
      if (length $self->{label} > 5)
      {
        $error = 1;
        $errorString .= "label = '$self->{label}' is invalid!<br>\n";
      }
    }
    if ($self->{task} !~ /^(go|gosub|return|cancel|prev|call|noop)$/)
    {
      $error = 1;
      $errorString .= "task = '$self->{task}' is invalid!<br>\n";
    }
    if (length $self->{rel} > 0 && $self->{rel} ne "next")
    {
      $error = 1;
      $errorString .= "rel = '$self->{rel}' is invalid!<br>\n";
    }
    if ($self->{task} =~ /^(go|gosub)$/)
    {
      if (length $self->{dest} == 0)
      {
        $error = 1;
        $errorString .= "you must specify a dest URL when task = '$self->{task}'!<br>\n";
      }
    }
    if (length $self->{method} > 0 && $self->{method} !~ /^(get|post)$/)
    {
      $error = 1;
      $errorString .= "method = '$self->{method}' is invalid!<br>\n";
    }
    if ($self->{method} eq "post" && length $self->{postdata} == 0)
    {
      $error = 1;
      $errorString .= "postdata = '$self->{postdata}' is invalid when method = 'post'!<br>\n";
    }
    if (length $self->{friend} > 0 && $self->{friend} !~ /^(true|false)$/)
    {
      $error = 1;
      $errorString .= "friend = '$self->{friend}' is invalid!<br>\n";
    }
    if (length $self->{sendreferer} > 0 && $self->{sendreferer} !~ /^(true|false)$/)
    {
      $error = 1;
      $errorString .= "sendreferer = '$self->{sendreferer}' is invalid!<br>\n";
    }
    if (length $self->{clear} > 0 && $self->{clear} !~ /^(true|false)$/)
    {
      $error = 1;
      $errorString .= "clear = '$self->{clear}' is invalid!<br>\n";
    }
    if ($self->{task} eq "call" && length $self->{number} == 0)
    {
      $error = 1;
      $errorString .= "number = '$self->{number}' is invalid when task = 'call'!<br>\n";
    }
    if (length $self->{src} > 0 && (length $self->{label} == 0 || length $self->{label} > 5))
    {
      $error = 1;
      $errorString .= "label = '$self->{label}' is invalid when src defined!<br>\n";
    }
    if (length $self->{icon} > 0 && (length $self->{label} == 0 || length $self->{label} > 5))
    {
      $error = 1;
      $errorString .= "label = '$self->{label}' is invalid when icon defined!<br>\n";
    }
  }
  elsif ($self->{cardType} eq "choice")
  {
    if (length $self->{name} == 0)
    {
      $error = 1;
      $errorString .= "name = '$self->{name}' is invalid!<br>\n";
    }
    if (length $self->{markable} > 0 && $self->{markable} !~ /^(true|false)$/)
    {
      $error = 1;
      $errorString .= "markable = '$self->{markable}' is invalid!<br>\n";
    }
    if (length $self->{method} > 0 && $self->{method} !~ /^(number|alpha)$/)
    {
      $error = 1;
      $errorString .= "method = '$self->{method}' is invalid!<br>\n";
    }
  }
  elsif ($self->{cardType} eq "nodisplay")
  {
    if (length $self->{name} == 0)
    {
      $error = 1;
      $errorString .= "name = '$self->{name}' 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};
}

# setFocus
# takes: location
# returns: old location
sub setFocus
{
  my $self = shift;
  my $location = shift;
  my $errStr = "HTMLObject::HDMLCard->setFocus()  - Error!<br>\n";
  my $oldFocus = $self->{location};
  
  if (length $location == 0)
  {
    return $oldFocus;
  }
  
  if ($location !~ /^(actions|content)$/)
  {
    $self->{error} = 1;
    $self->{errorString} = $errStr . "location = '$location' is invalid!<br>\n";
    return "";
  }
  
  if ($self->{cardType} eq "nodisplay" && $location eq "content")
  {
    $self->{error} = 1;
    $self->{errorString} = $errStr . "location = '$location' is invalid when cardType = 'nodisplay'!<br>\n";
    return "";
  }
  
  $self->{location} = $location;
  
  return $oldFocus;
}

# print
# takes: content
# returns: nothing
sub print
{
  my $self = shift;
  my $content = shift;
  my $errStr = "HTMLObject::HDMLCard->print()  - Error!<br>\n";
  
  if ($self->{cardType} eq "action")
  {
    $self->{error} = 1;
    $self->{errorString} = $errStr . "you can not print into an 'action' card!<br>\n";
    return;
  }
  
  if ($self->{location} eq "actions")
  {
    $self->{actions} .= $content;
  }
  elsif ($self->{location} eq "content")
  {
    $self->{content} .= $content;
  }
}

# display
# takes: nothing
# returns: string containg the card info to display.
sub display
{
  my $self = shift;
  my $errStr = "HTMLObject::HDMLCard->display()  - Error!<br>\n";
  my $output = "";
  
  if ($self->{cardType} eq "display")
  {
    $output = "  <display name=$self->{name}";
    $output .= " title=\"$self->{title}\"" if (length $self->{title} > 0);
    $output .= " markable=$self->{markable}" if (length $self->{markable} > 0);
    $output .= " bookmark=$self->{bookmark}" if (length $self->{bookmark} > 0);
    $output .= ">\n";
    (my $actions = $self->{actions}) =~ s/^(.*)$/    $1/mg;
    $output .= $actions . (length $self->{actions} > 0 ? "\n" : "");
    (my $content = $self->{content}) =~ s/^(.*)$/    $1/mg;
    $output .= $content . (length $self->{content} > 0 ? "\n" : "");
    $output .= "  </display>\n";
  }
  elsif ($self->{cardType} eq "entry")
  {
    $output = "  <entry name=$self->{name}";
    $output .= " title=\"$self->{title}\"" if (length $self->{title} > 0);
    $output .= " markable=$self->{markable}" if (length $self->{markable} > 0);
    $output .= " bookmark=$self->{bookmark}" if (length $self->{bookmark} > 0);
    $output .= " format=$self->{format}" if (length $self->{format} > 0);
    $output .= " default=$self->{default}" if (length $self->{default} > 0);
    $output .= " key=$self->{key}" if (length $self->{key} > 0);
    $output .= " noecho=$self->{noecho}" if (length $self->{noecho} > 0);
    $output .= " emptyok=$self->{emptyok}" if (length $self->{emptyok} > 0);
    $output .= ">\n";
    (my $actions = $self->{actions}) =~ s/^(.*)$/    $1/mg;
    $output .= $actions . (length $self->{actions} > 0 ? "\n" : "");
    (my $content = $self->{content}) =~ s/^(.*)$/    $1/mg;
    $output .= $content . (length $self->{content} > 0 ? "\n" : "");
    $output .= "  </entry>\n";
  }
  elsif ($self->{cardType} eq "action")
  {
    $output = "  <action type=$self->{type}";
    $output .= " label=$self->{label}" if (length $self->{label} > 0);
    $output .= " task=$self->{task}" if (length $self->{task} > 0);
    $output .= " dest=$self->{dest}" if (length $self->{dest} > 0);
    $output .= " rel=next" if (length $self->{rel} > 0);
    $output .= " method=$self->{method}" if (length $self->{method} > 0);
    $output .= " postdata=$self->{postdata}" if (length $self->{postdata} > 0);
    $output .= " accept-charset=$self->{acceptCharset}" if (length $self->{acceptCharset} > 0);
    $output .= " vars=$self->{vars}" if (length $self->{vars} > 0);
    $output .= " receive=$self->{receive}" if (length $self->{receive} > 0);
    $output .= " retvals=$self->{retvals}" if (length $self->{retvals} > 0);
    $output .= " next=$self->{next}" if (length $self->{next} > 0);
    $output .= " cancel=$self->{cancel}" if (length $self->{cancel} > 0);
    $output .= " friend=$self->{friend}" if (length $self->{friend} > 0);
    $output .= " sendreferer=$self->{sendreferer}" if (length $self->{sendreferer} > 0);
    $output .= " clear=$self->{clear}" if (length $self->{clear} > 0);
    $output .= " number=$self->{number}" if (length $self->{number} > 0);
    $output .= " src=$self->{src}" if (length $self->{src} > 0);
    $output .= " icon=$self->{icon}" if (length $self->{icon} > 0);
    $output .= ">\n";
  }
  elsif ($self->{cardType} eq "choice")
  {
    $output = "  <choice name=$self->{name}";
    $output .= " title=\"$self->{title}\"" if (length $self->{title} > 0);
    $output .= " markable=$self->{markable}" if (length $self->{markable} > 0);
    $output .= " bookmark=$self->{bookmark}" if (length $self->{bookmark} > 0);
    $output .= " key=$self->{key}" if (length $self->{key} > 0);
    $output .= " ikey=$self->{ikey}" if (length $self->{ikey} > 0);
    $output .= " method=$self->{method}" if (length $self->{method} > 0);
    $output .= " default=$self->{default}" if (length $self->{default} > 0);
    $output .= " idefault=$self->{idefault}" if (length $self->{idefault} > 0);
    $output .= ">\n";
    (my $actions = $self->{actions}) =~ s/^(.*)$/    $1/mg;
    $output .= $actions . (length $self->{actions} > 0 ? "\n" : "");
    (my $content = $self->{content}) =~ s/^(.*)$/    $1/mg;
    $output .= $content . (length $self->{content} > 0 ? "\n" : "");
    $output .= "  </choice>\n";
  }
  elsif ($self->{cardType} eq "nodisplay")
  {
    $output = "  <nodisplay name=$self->{name}>\n";
    (my $actions = $self->{actions}) =~ s/^(.*)$/    $1/mg;
    $output .= $actions . (length $self->{actions} > 0 ? "\n" : "");
    $output .= "  </nodisplay>\n";
  }
  
  return $output;
}

1;
__END__

=head1 NAME

HDMLCard - Object used to build a HDMLCard Object Class.

=head1 SYNOPSIS

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

=head1 DESCRIPTION

HDMLCard is a HDMLCard class.

=head1 Exported FUNCTIONS

  scalar new(void)
    Creates a new instance of the HTMLObject::HDMLCard
    object.

  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.
    
  scalar setFocus(scalar)
    Returns the old focus and sets the new focus to the specified 
    location (content or actions).  If nothing specified just returns
    the old focus.

  void print(scalar)
    Adds the contents of the passed in string to the content string or
    to the actions string if the focus is so located.
    
  scalar display(void)
    Returns the corresponding HDML card definition that defines the
    contents of this 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
