# ==================================================================
# Gossamer Threads Module Library - http://gossamer-threads.com/
#
#       GT::SQL::Display::HTML
#       Author: Scott & Alex
#       $Id: Relation.pm,v 1.18 2004/08/28 03:53:45 jagerman Exp $
#
# Copyright (c) 2004 Gossamer Threads Inc.  All Rights Reserved.
# ==================================================================
#
# Description:
#       HTML module that provides a set of method to control your
# user display in order to get rid of HTML coding inside CGI script.
#

package GT::SQL::Display::HTML::Relation;
# ===============================================================
    use strict;
    use vars qw/@ISA $AUTOLOAD $VERSION $ERROR_MESSAGE $ATTRIBS $DEBUG $FONT %SIZE_FORMS/;
    use GT::SQL::Display::HTML;

    @ISA             = qw/GT::SQL::Display::HTML/;
    $FONT            = 'face="Tahoma,Arial,Helvetica" size=2';
    $VERSION         = sprintf "%d.%03d", q$Revision: 1.18 $ =~ /(\d+)\.(\d+)/;
    $DEBUG           = 0;
    $ERROR_MESSAGE   = 'GT::SQL';

    $ATTRIBS = {
        db          => undef, 
        input       => undef,
        code        => {},
        mode        => '',
        font        => $FONT,
        hide_timestamp => 0,
        view_key    => 0,
        defaults    => 0,
        search_opts => 0,
        values      => {},
        multiple    => 0,
        table       => 'border=0 width=500',
        tr          => '',
        td          => 'valign=top align=left',
        extra_table => 1,
        col_font    => $FONT,
        val_font    => $FONT,
        hide        => [],
        skip        => [],
        view        => [],
        disp_form   => 1,
        disp_html   => 0,
        file_field  => 0,
        file_delete => 0,
        file_use_path => 0,
    };

sub display {
# ---------------------------------------------------------------
# Display a record as html.
#
    my $self  = shift;
    my $opts  = shift;
    $self->reset_opts;
    $opts->{disp_form} = 0;
    $opts->{disp_html} = 1;
    return $self->_display ($opts || ());
}

sub _display {
# ---------------------------------------------------------------
# Handles displaying of a form or a record.
#
    my $self = shift;

# Initiate if we are passed in any arguments as options.
    if (@_) { $self->init (@_); }

# Get the column hash and primary key
    $self->{pk}   = [$self->{db}->pk] unless $self->{pk};
    $self->{cols} = $self->{db}->ordered_columns;

# Output
    my $out   = '';
    
# Hide the primary keys.
    $self->{view_key} and push (@{$self->{view}}, @{$self->{pk}}) if ($self->{pk});

# Now go through each column and print out a column row.
    my @ntables = values %{$self->{db}->{tables}};
    my (@tmp, @tables);
    for my $t (@ntables) {
        my @cols  = $t->ordered_columns;
        my %fk    = $t->fk;
        my %cols  = $t->cols;
        my $name  = $t->name;
        my $found = 0;
        COL: foreach my $col_name (@cols) {
            if (exists $self->{values}->{$col_name}) {
                $self->{values}->{$name . '.' . $col_name} = delete $self->{values}->{$col_name};
            }
            $self->{cols}->{$name . '.' . $col_name} = $cols{$col_name};
            FK: for (keys %fk) {
                if (exists $self->{db}->{tables}->{$_}) {
                    if (exists $fk{$_}->{$col_name}) {
                        $found = 1;
                        last FK;
                    }
                }
            }
        }
        $found ? (push (@tmp, $t)) : (@tables = ($t));
    }
    push @tables, @tmp;

# Calculate the form values.
    my $values  = $self->_get_defaults;

# Set the table widths depending on if we need a third column.
    my ($cwidth, $vwidth) = ('30%', '70%');
    if ($self->{search_opts}) { $cwidth = "30%"; $vwidth = "60%" }

    for my $table (@tables) {
        $out .= $self->mk_table (
            table  => $table,
            values => $values,
            cwidth => $cwidth,
            vwidth => $vwidth
        );
    }
    $out .= '<br>';

    foreach (@{$self->{hide}}) {
        my $field_name = $self->{multiple} ? "$self->{multiple}-$_" : $_;
        my $val = $values->{$_};
        if (exists $self->{cols}->{$_}->{time_check} and $self->{cols}->{$_}->{time_check}) {
            $val ||= $self->_get_time ($self->{cols}->{$_});
        }
        defined $val or ($val = '');
        GT::SQL::Display::HTML::_escape(\$val); 
        $out .= qq~<input type="hidden" name="$field_name" value="$val">~; 
    }
    $self->{extra_table} and ($out .= "</td></tr></table>\n");
    return $out;
}

sub mk_table {
    my $self = shift;
    my %opt = @_;

    my $out = '';
    $self->{extra_table} and ($out .= "<p><table border=1 cellpadding=0 cellspacing=0><tr><td>");
    my $cols = $opt{table}->cols;
    my $name = $opt{table}->name;

    $out .= qq(
        <table $self->{table}>
        <tr><td colspan=3 bgcolor=navy>
            <FONT FACE="MS Sans Serif, arial,helvetica" size=1 COLOR="#FFFFFF">$name</font>
        </td></tr>
    );
    my @cols = $opt{table}->ordered_columns;
    my %fk   = $opt{table}->fk;

    COL: foreach my $col_name (@cols) {
        $out .= $self->mk_row (%opt, col_name => $col_name, fk => \%fk);
    }
    $out .= "</table>\n";
    $out .= "</table></p>\n" if $self->{extra_table};
    return $out;
}

sub mk_row {
    my $self = shift;
    my %opt  = @_;
    my $out = '';
    for (keys %{$opt{fk}}) {
        if (exists $self->{db}->{tables}->{$_}) {
            (exists $opt{fk}->{$_}->{$opt{col_name}}) and return '';
        }
    }
    my $col = $opt{table}->name . '.' . $opt{col_name};

# Run any code refs that have been setup.
    if (exists $self->{code}->{$col} and (ref $self->{code}->{$col} eq 'CODE')) {
        $out .= $self->{code}->{$col}->($self, $self->{cols}->{$col}, $opt{values});
        return '';
    }
    return '' if $self->_skip ($col);

# Set the form name (using increment for multiple if requested) and also the display name.
    my $field_name   = $self->{multiple} ? "$self->{multiple}-$col" : $col;
    my $display_name = exists ($self->{cols}->{$col}->{form_display}) ? $self->{cols}->{$col}->{form_display} : $col;
    my $value = $opt{values}->{$col};
    my $disp = $self->{disp_form} ? $self->_get_form_display ($col) : $self->_get_html_display ($col);

    $disp eq 'hidden' and push (@{$self->{hide}}, $col) and return '';
    $out .= "<tr $self->{tr}><td $self->{td} width='$opt{cwidth}'><font $self->{col_font}>$display_name</font></td><td $self->{td} width='$opt{vwidth}'><font $self->{val_font}>";

# Get the column display subroutine
    $out .= $self->$disp( { name => $field_name, def => $self->{cols}->{$col}, value => $value }, $opt{values}, $self );

    $out .= "</font></td>";

# Display any search options if requested.
    if ($self->{search_opts}) {
        my $is_pk = 0;
        for (@{$self->{pk}}) {
            $is_pk = 1, last if ($_ eq $col);
        }
        
        $out .= qq~<td $self->{td} width="10%"><font $self->{val_font}>~;
        $out .= $self->_mk_search_opts({
            name => $field_name,
            def  => $self->{cols}->{$col},
            pk   => $is_pk
        }) || '&nbsp;';
        $out .= "</font></td>";
    }
    $out .= "\n";
    return $out;

}

sub _get_defaults {
# -------------------------------------------------------------------
# Returns default values for fields. Bases it on what's passed in,
# cgi input, def file defaults, otherwise blank.
#
    my $self    = shift;

    my @ntables = values %{$self->{db}->{tables}};
    my @cols = $self->{db}->ordered_columns;
    my $c       = $self->{cols};
    my $values  = {};
    foreach my $col (@cols) {
        my $value = '';
        if    (exists $self->{values}->{$col})                  { $value = $self->{values}->{$col} }
        elsif (exists $self->{input}->{$col})                   { $value = $self->{input}->{$col} }
        elsif ($self->{defaults} and exists $c->{$col}->{default})  {
            if ($c->{$col}->{type} =~ /DATE|TIME|YEAR/) {
                (defined $c->{$col}->{default} and $c->{$col}->{default} =~ /0000/)
                    ? ($value = $self->_get_time($c->{$col}))
                    : ($value = $c->{$col}->{default});
            }
            else {
                $value = $c->{$col}->{default};
            }
        }
        elsif ($self->{defaults} and $c->{$col}->{type} =~ /DATE|TIME|YEAR/) { 
            $value = $self->_get_time($c->{$col});
        }
        $values->{$col} = $value;
    }
    return $values;
}

1;

__END__

=pod

# Options for display forms/views:
#       hide_timestamp  => 1        # Do not display timestamp fields.
#       search_opts     => 1        # Add search options boxes.
#       multiple        => 1        # Prepend $multiple- to column names.
#       defaults        => 1        # Use .def defaults.
#       values          => {}       # hash ref of values to use (overrides input)
#       table           => 'string' # table properties, defaults to 0 border.
#       tr              => 'string' # table row properties, defaults to none.
#       td              => 'string' # table cell properties, defaults to just aligns.
#       extra_table     => 0        # disable wrap form in extra table for looks.
#       col_font        => 'string' # font to use for columns, defaults to $FONT.
#       val_font        => 'string' # font to use for values, defaults to $FONT.
#       hide            => []       # display fields as hidden tags.
#       view            => []       # display fields as html with hidden tags as well.
#       skip            => []       # don't display array of column names.

=cut
