# ==================================================================
# Gossamer Links - enhanced directory management system
#
#   Website  : http://gossamer-threads.com/
#   Support  : http://gossamer-threads.com/scripts/support/
#   CVS Info : 087,071,086,086,085      
#   Revision : $Id: SiteHTML.pm,v 1.89 2008/04/29 04:02:34 brewt Exp $
#
# Copyright (c) 2004 Gossamer Threads Inc.  All Rights Reserved.
# Redistribution in part or in whole strictly prohibited. Please
# see LICENSE file for full details.
# ==================================================================

package Links::SiteHTML;
# ==================================================================
use strict;
use Links qw/:objects :payment/;

sub display {
# -----------------------------------------------------------------
# Returns a specified template parsed.
#
    my ($template, $vars, $opts) = @_;
    my $code = exists $Links::SiteHTML::{"site_html_$template"} ? $Links::SiteHTML::{"site_html_$template"} : _compile("site_html_$template");
    defined $code or die "Invalid method: site_html_$template called.";

    $PLG->dispatch("site_html_$template", $code, $vars, $opts);
}

sub tags {
# -----------------------------------------------------------------
# Returns the tags needed to properly include a template in another template,
# instead of returning parsed HTML like display().  Currently only supports
# 'link' for formatted link information.
#
    my ($sub, $vars, $opts) = @_;
    my $code = exists $Links::SiteHTML::{"site_tags_$sub"} && $Links::SiteHTML::{"site_tags_$sub"};
    defined $code or die "Invalid method: site_tags_$sub called.";

    $PLG->dispatch("site_tags_$sub", $code, $vars, $opts);
}

# All the templates are auto-loaded, except for the ones below which need
# to do some special stuff.

sub site_tags_link {
# --------------------------------------------------------
# Format the tags for a single link.
#
    my ($vars, $cat_id) = @_;

    my %block = $Links::GLOBALS ? map { $_ => 1 } keys %$Links::GLOBALS : ();
    my %rec = map { exists $block{$_} ? () : ($_ => $vars->{$_}) } keys %$vars;

    $rec{Add_Date_time} = GT::Date::timelocal(GT::Date::parse_format($rec{Add_Date}, GT::Date::FORMAT_DATE));
    $rec{Mod_Date_time} = GT::Date::timelocal(GT::Date::parse_format($rec{Mod_Date}, GT::Date::FORMAT_DATE));

# Convert the date formats.
    if (GT::Date::FORMAT_DATE ne $CFG->{date_user_format}) {
        Links::init_date();
        $rec{Add_Date} = GT::Date::date_transform($rec{Add_Date}, GT::Date::FORMAT_DATE, $CFG->{date_user_format}) || $rec{Add_Date};
        $rec{Mod_Date} = GT::Date::date_transform($rec{Mod_Date}, GT::Date::FORMAT_DATE, $CFG->{date_user_format}) || $rec{Mod_Date};
    }

# Set new and pop to either 1 or undef for templates.
    $rec{isNew}     = ($rec{isNew}     and ($rec{isNew}     eq 'Yes' or $rec{isNew}     eq '1')) ? 1 : 0;
    $rec{isChanged} = ($rec{isChanged} and ($rec{isChanged} eq 'Yes' or $rec{isChanged} eq '1')) ? 1 : 0;
    $rec{isPopular} = ($rec{isPopular} and ($rec{isPopular} eq 'Yes' or $rec{isPopular} eq '1')) ? 1 : 0;
    $rec{isLinkOwner} = ($USER and defined $USER->{Username} and $rec{LinkOwner} eq $USER->{Username}) ? 1 : 0;

    $rec{paymentsEnabled} = 0; # The payment url is disabled by default

    if ($CFG->{payment}->{enabled}) {
        my $catp;
# Fetch payment information for the category the link is in (used below to determine if the payment data should be shown)
        my @cid = $DB->table('CatLinks')->select('CategoryID', { LinkID => $rec{ID} })->fetchall_list;
        require Links::Payment;
        $catp = Links::Payment::load_cat_price(\@cid);

        # Add various extra tags regarding payment if the current user is the link owner:
        if ($rec{isLinkOwner} and $rec{ExpiryDate} != UNLIMITED and $catp->{payment_mode} != NOT_ACCEPTED) {
            my $expiry_date = $rec{ExpiryDate};
            my $notify_date = time + $CFG->{payment}->{expiry_notify} * (24*60*60);
            $rec{paymentsEnabled} = 1;
            $rec{isUnpaid}  = $expiry_date == UNPAID;
            $rec{isFree}    = $expiry_date == FREE;
            $rec{isExpired} = ($expiry_date > UNPAID and $expiry_date < time or $rec{isFree} and $rec{LinkExpired});
            $rec{wasPaid}   = ($expiry_date > UNPAID and $expiry_date < FREE or $rec{isFree} and $rec{LinkExpired});
            $rec{ExpiryDateFormatted} = ($expiry_date > UNPAID and $expiry_date < FREE)
                ? GT::Date::date_get($expiry_date, $CFG->{date_expiry_format})
                : ($rec{isFree} and $rec{LinkExpired})
                  ? GT::Date::date_get($rec{LinkExpired}, $CFG->{date_expiry_format})
                  : '';
            $rec{isNotify}  = ($expiry_date >= time and $expiry_date <= $notify_date) ? 1 : 0;
        }

        $rec{isPaidLink} = 0;
        $rec{isFreeLink} = 0;
        if ($rec{ExpiryDate} >= time and $rec{ExpiryDate} < FREE) {
            $rec{isPaidLink} = 1;
        }
        elsif ($rec{ExpiryDate} == FREE) {
            $rec{isFreeLink} = 1;
        }
    }

    my $links = $DB->table('Links');
    if ($CFG->{build_detailed}) {
        my $detailed;
# Generate the detailed url for a specific the category that we're in (a link may be in multiple categories)
        if ($cat_id) {
            $detailed = $links->category_detailed_url($cat_id, $rec{ID});
        }
        else {
            $detailed = $links->detailed_url($rec{ID});
        }
        $rec{detailed_url} = "$CFG->{build_detail_url}/$detailed";
    }

# Load any reviews, if not already done
    $links->add_reviews(\%rec) unless exists $rec{Review_Loop};

    \%rec;
}

sub site_html_link {
# --------------------------------------------------------
# Format and return the HTML for a single link.
#
# Note that this method is deprecated in favour of generating all the html in
# the templates.  Instead, you should be doing:
# <%Links::Utils::load_link_info%><%include link.html%>
#
    my $rec = tags(link => @_);

# Set the template set to use.
    my $opts = { dynamic => 0 };
    if ($rec->{Category_Template} and $rec->{Category_Template} =~ /^[\w-]+(\.[\w-]+)?$/ and (not $1 or ($1 ne '.html' and $1 ne '.htm'))) {
        $opts->{template} = delete $rec->{Category_Template};
    }

# Parse the template.
    return Links::user_page('link.html', $rec, $opts);
}

sub site_html_detailed {
# --------------------------------------------------------
# Return parsed detailed page (one link per html page).
#
    my $rec = shift;

    $rec->{Add_Date_time} = GT::Date::timelocal(GT::Date::parse_format($rec->{Add_Date}, GT::Date::FORMAT_DATE));
    $rec->{Mod_Date_time} = GT::Date::timelocal(GT::Date::parse_format($rec->{Mod_Date}, GT::Date::FORMAT_DATE));

# Convert the date formats.
    if (GT::Date::FORMAT_DATE ne $CFG->{date_user_format}) {
        Links::init_date();
        $rec->{Add_Date_orig} = $rec->{Add_Date};
        $rec->{Add_Date} = GT::Date::date_transform($rec->{Add_Date}, GT::Date::FORMAT_DATE, $CFG->{date_user_format}) || $rec->{Add_Date};
        $rec->{Mod_Date_orig} = $rec->{Mod_Date};
        $rec->{Mod_Date} = GT::Date::date_transform($rec->{Mod_Date}, GT::Date::FORMAT_DATE, $CFG->{date_user_format}) || $rec->{Mod_Date};
    }

# Set new and pop to either 1 or undef for templates.
    $rec->{isNew}     = ($rec->{isNew}     and ($rec->{isNew}     eq 'Yes' or $rec->{isNew}     eq '1')) ? 1 : 0;
    $rec->{isChanged} = ($rec->{isChanged} and ($rec->{isChanged} eq 'Yes' or $rec->{isChanged} eq '1')) ? 1 : 0;
    $rec->{isPopular} = ($rec->{isPopular} and ($rec->{isPopular} eq 'Yes' or $rec->{isPopular} eq '1')) ? 1 : 0;
    $rec->{isLinkOwner} = ($USER and defined $USER->{Username} and $rec->{LinkOwner} eq $USER->{Username}) ? 1 : 0;

    if ($CFG->{payment}->{enabled}) {
        $rec->{isPaidLink} = 0;
        $rec->{isFreeLink} = 0;
        if ($rec->{ExpiryDate} >= time and $rec->{ExpiryDate} < FREE) {
            $rec->{isPaidLink} = 1;
        }
        elsif ($rec->{ExpiryDate} == FREE) {
            $rec->{isFreeLink} = 1;
        }
    }

# Set the template set to use.
    my $opts = { dynamic => 1 };
    if ($rec->{Category_Template} and $rec->{Category_Template} =~ /^[\w-]+(\.[\w-]+)?$/ and (not $1 or ($1 ne '.html' and $1 ne '.htm'))) {
        $opts->{template} = delete $rec->{Category_Template};
    }

    my $output = Links::user_page('detailed.html', $rec, $opts);
    return $output;
}

sub site_html_category {
# --------------------------------------------------------
# Return parsed category page.
#
    my $tags = shift;

    $tags->{build_links_per_page} = $CFG->{build_links_per_page};
    ($tags->{category_first}) = $tags->{'category_name'} =~ m,/?([^/]+)$,;

    my $opts = { dynamic => 1 };

# Find the proper template.
    my $template = 'category.html';

# If the Category_Template ends with .htm or .html, then use that file as a template, otherwise, use it as a template set.
    if ($tags->{Category_Template} and $tags->{Category_Template} =~ /^[\w-]+(\.[\w-]+)?$/ and (not $1 or ($1 ne '.html' and $1 ne '.htm'))) {
        $opts->{template} = delete $tags->{Category_Template};
    }
    elsif ($tags->{Category_Template}) {
        $template = $tags->{Category_Template};
    }
    my $output = Links::user_page($template, $tags, $opts);
    return $output;
}

sub site_html_print_cat {
# --------------------------------------------------------
# This routine prints out a list of categories.
#
# Note that this method has been deprecated in favour of using loops and
# performing html generation in the templates.  If you need to modify
# the category data, use the build_category_loop plugin hook.
#
    my @subcat     = @{$_[0]};
    my $parent_cat = shift @subcat;
    my $breakpoint = int(@subcat / $CFG->{build_category_columns});
    $breakpoint++ if @subcat % $CFG->{build_category_columns};
    my $table_head = $CFG->{build_category_table} || '';
    my $width      = int(100 / $CFG->{build_category_columns});
    my $output     = '';
    my $i          = 0;
    my $cat_db     = $DB->table('Category');
    my $opts       = { dynamic => 0 };

# Print Header.
    if ($CFG->{build_category_columns}) {
        $output = qq|<div class="margin"><table $table_head><tr><td class="catlist" width="$width%" valign="top">\n|;
    }

# Figure out if we should use a different template.
    if ($parent_cat->{Category_Template} and $parent_cat->{Category_Template} =~ /^[\w-]+(\.[\w-]+)?$/ and (not $1 or ($1 ne '.html' and $1 ne '.htm'))) {
        $opts->{template} = delete $parent_cat->{Category_Template};
    }

# Go through each subcategory and print its template.
    for my $cat_r (@subcat) {
        $cat_r->{Short_Name} = $cat_r->{Name} =~ m,.*/([^/]+)$, ? $1 : $cat_r->{Name};
        $cat_r->{URL}      ||= $CFG->{build_root_url} . "/" . $cat_db->as_url($cat_r->{Full_Name}) . "/" . ($CFG->{build_index_include} ? $CFG->{build_index} : '');

# Set the short name.
        if ($cat_r->{Related}) {
            if ($cat_r->{RelationName}) {
                $cat_r->{Short_Name} = $cat_r->{RelationName};
            }
            else {
                if (exists $parent_cat->{Name} and ($cat_r->{Short_Name} eq $parent_cat->{Name})) {
                    my ($short) = $cat_r->{Full_Name} =~ m,([^/]+)/[^/]*$,;
                    $short and ($cat_r->{Short_Name} = $short);
                }
                else {
                    $cat_r->{Short_Name} = $cat_r->{Short_Name};
                }
            }
        }

# We check to see if we are half way through, if so we stop this table cell
# and begin a new one (this lets us have category names in two columns).
        if ($CFG->{build_category_columns}) {
            $output .= qq|</td>\n<td valign="top" width="$width%" class="catlist">\n| if $i > 0 and not $i % $breakpoint;
            $i++;
        }
        $output .= Links::user_page('subcategory.html', $cat_r, $opts);
    }

# Don't forget to end the table properly ..
    if ($CFG->{build_category_columns}) {
        $output .= "</td></tr></table></div>\n";
    }
    return $output;
}

sub site_html_error {
# --------------------------------------------------------
# Print out the error page
#
    my ($vars, $opts) = @_;
    $opts ||= { dynamic => 1 };
    unless (exists $vars->{main_title_loop}) {
        require Links::Build;
        $vars->{main_title_loop} = Links::Build::build('title', Links::language('LINKS_ERROR'), $CFG->{build_root_url} . "/" . ($CFG->{build_home} || ($CFG->{build_index_include} ? $CFG->{build_index} : '')));
    }
    return Links::user_page('error.html', $vars, $opts);
}

sub _compile {
# -------------------------------------------------------------------
# Compile dynamically creates site_html routines if a template file
# exists.
#
    my $sub = shift;
    my ($file) = $sub =~ /^site_html_([\w-]+)$/;
    $file or return sub { display('error', { error => "Invalid SiteHTML method: '" . $IN->html_escape($sub) . "'." }) };
    $file .= '.html';
    my $template_set = Links::template_set();
    unless (Links::template_exists($template_set, $file)) {
        return sub { display('error', { error => "Invalid SiteHTML method: $sub ($file).  The template does not exist in '$template_set'." }) };
    }
    my $code = sub { my ($vars, $opts) = @_; $opts ||= { dynamic => 1 }; return Links::user_page($file, $vars, $opts) };
    $Links::SiteHTML::{$sub} = $code;
    $code;
}

1;
