#!/usr/bin/perl
use strict;
use Time::HiRes qw(gettimeofday tv_interval);
use Data::Dumper;
use XML::LibXML;
use XML::LibXSLT;
use HTML::Template;
use Template;
use File::Temp qw(tmpnam);


my ($xslt_timer, $html_timer, $tt2_timer);
my ($xml_parser, $xsl_parser) = (XML::LibXML->new, XML::LibXSLT->new);

my $big_array = build_big_array(5000);
my $xml_data = build_xml_data($big_array);
my $template_obj = build_html_template();
my $html3 = render_tt2($big_array);
my $xsl = build_xsl_processor();

my $html1 = render_html_template($template_obj, $big_array);
my $html2 = render_xslt($xsl, $xml_data );

save_output($html1, $html2, $html3);
print<<EOK;
HTML Template Time : $html_timer
XSLT Time          : $xslt_timer
TT2 Time           : $tt2_timer
EOK

sub build_big_array
{
    my $count = shift;
    my $data = _read_chunk ('data');
    my @big_array;
    my $h = eval $data;
    for (my $i=0 ; $i < $count; $i++) { push (@big_array, $h); }
    return \@big_array;
}

sub build_xml_data
{
    my $data_array = shift;
    my $t0 = [gettimeofday];
    my $xml_data = "<results>";
    foreach my $data (@$data_array)
    {
        $xml_data .= "<r>\n";
        foreach my $k (keys %$data)
        {
            $xml_data .= "<$k><![CDATA[$data->{$k}]]></$k>\n";
        }
        $xml_data .= "</r>\n";
    }
    $xml_data .= "</results>";
    #print "$xml_data\n";
    my $dom = $xml_parser->parse_string($xml_data);
    $xslt_timer += tv_interval($t0, [gettimeofday]);
    return $dom;
}

sub build_xsl_processor
{
    my $str = _read_chunk ('xsl');
    my $xsl = $xml_parser->parse_string ($str);
    return $xsl_parser->parse_stylesheet($xsl);
}

sub build_html_template
{
    my $tmpl = _read_chunk ('template');
    return HTML::Template->new( scalarref => \$tmpl );
}

sub _read_chunk
{
    my $starter = shift;
    my ($running, $stop, $data) = (0,0);
    while (<DATA>)
    {
        next unless (/^\$$starter/ || $running);
        $running = 1;
        chomp;
        s/^\s+//;
        s/\s+$//;
        next if /^\$$starter/;
        $stop++ if length($_) == 0;
        last if $stop == 2;
        $data .= $_;
    }
    return $data;
}

sub render_html_template
{
    my ($template_obj, $data) = @_;
    my $t0 = [gettimeofday];
    $template_obj->param(TR_LOOP => $data);
    my $html= $template_obj->output;
    $html_timer += tv_interval($t0, [gettimeofday]);
    return $html;
}

sub render_xslt
{
    my $xsl_proc = shift;
    my $xml_dom = shift;
    # timer starts here
    my $t0 = [gettimeofday];
    my $html = $xsl_proc->output_string($xsl_proc->transform($xml_dom));
    $xslt_timer += tv_interval($t0, [gettimeofday]);
    return $html;
}

sub render_tt2
{
    my ($data) = @_;
    my $o_tt2 = Template->new({
                                ABSOLUTE => 1,
                              });
    my $templ = _read_chunk('tt_template');
    my $filename =  tmpnam();
    open (F, ">$filename");
    print F $templ;
    close F;

    my $str;
    $o_tt2->process($filename,{data => $data},\$str);

    # need to process twice since first one would  not use cached template
    my $str_new;
    my $t0 = [gettimeofday];
    unless ($o_tt2->process($filename,{data => $data},\$str_new))
    {
        print STDERR "TT2 ERROR ",$o_tt2->error(),"\n";
    }
    $tt2_timer += tv_interval($t0);
    unlink $filename;
    return $str_new;
}

sub save_output
{
    my ($h1, $h2, $h3) = @_;
    open (F, ">html_template.html") ;
    print F $h1,"\n" ;
    close F;

    open (F, ">html_xslt.html");
    print F $h2,"\n" ;
    close F;

    open (F, ">html_tt2.html");
    print F $h3,"\n" ;
    close F;
}

__DATA__
$data=
{
         id => 100,
         p_name => 'JOHN',
         ap_time => '20050324 18-24-00',
         ap_tzr => 'US/Eastern',
         ap_tzra => 'EST',
         p_id => 109,
         ap_phone => '617 249 5000',
         ap => 'John Hopkins',
         ap_loc => 'Washington DC',
         ct_time => '20050405 10-32-00',
         ct_tzr => 'US/Pacific',
         ct_tzra => 'PST',
         count => 5,
}


$template=
<html><body>
<table tabindex='16' cellspacing='0' id='results_tbl' style='width:100%;margin:0px;margin-top:1px;padding:0px;' cellpadding='0' class='apptstable sort-table' >
<thead><tr><th>ID</th><th>Patient Name</th><th style=''>Appt Time</th><th style=''>App Timezone</th><th style=''>Timezone</th><th style=''>Patient ID</th><th style=''>Appt Phone</th><th>Appt Prov</th><th>Appt Location</th><th>Call Time</th><th>Timezone</th><th>Timezone</th><th>Count</th></tr></thead>
<tbody>
<TMPL_LOOP NAME='TR_LOOP'>
<tr onmouseover='_results_tbl.rollOver(this);' onmouseout='_results_tbl.rollOut(this);' ondblclick='_results_tbl.dblclick(this);' onclick='_results_tbl.click({rowObject:this}, _results_tbl);'>
<td title='id'><TMPL_VAR NAME='id'></td>
<td title='p_name'><TMPL_VAR NAME='p_name'></td>
<td title='ap_time'><TMPL_VAR NAME='ap_time'></td>
<td title='ap_tzr'><TMPL_VAR NAME='ap_tzr'></td>
<td title='ap_tzra'><TMPL_VAR NAME='ap_tzra'></td>
<td title='p_id'><TMPL_VAR NAME='p_id'></td>
<td title='ap_phone'><TMPL_VAR NAME='ap_phone'></td>
<td title='ap'><TMPL_VAR NAME='ap'></td>
<td title='ap_loc'><TMPL_VAR NAME='ap_loc'></td>
<td title='ct_time'><TMPL_VAR NAME='ct_time'></td>
<td title='ct_tzr'><TMPL_VAR NAME='ct_tzr'></td>
<td title='ct_tzra'><TMPL_VAR NAME='ct_tzra'></td>
<td title='count'><TMPL_VAR NAME='count'></td>
</tr>
</TMPL_LOOP>
</table>
</body></html>


$tt_template=
<html><body>
<table tabindex='16' cellspacing='0' id='results_tbl' style='width:100%;margin:0px;margin-top:1px;padding:0px;' cellpadding='0' class='apptstable sort-table' >
<thead><tr><th>ID</th><th>Patient Name</th><th style=''>Appt Time</th><th style=''>App Timezone</th><th style=''>Timezone</th><th style=''>Patient ID</th><th style=''>Appt Phone</th><th>Appt Prov</th><th>Appt Location</th><th>Call Time</th><th>Timezone</th><th>Timezone</th><th>Count</th></tr></thead>
<tbody>
[% FOREACH tr=data %]
<tr onmouseover='_results_tbl.rollOver(this);' onmouseout='_results_tbl.rollOut(this);' ondblclick='_results_tbl.dblclick(this);' onclick='_results_tbl.click({rowObject:this}, _results_tbl);'>
<td title='id'>[% tr.id %]</td>
<td title='p_name'>[% tr.p_name %]></td>
<td title='ap_time'>[% tr.ap_time %]</td>
<td title='ap_tzr'>[% tr.ap_tzr %]</td>
<td title='ap_tzra'>[% tr.ap_tzra %]</td>
<td title='p_id'>[% tr.p_id %]</td>
<td title='ap_phone'>[% tr.ap_phone %]</td>
<td title='ap'>[% tr.ap %]</td>
<td title='ap_loc'>[% tr.ap_loc %]</td>
<td title='ct_time'>[% tr.ct_time %]</td>
<td title='ct_tzr'>[% tr.ct_tzr %]</td>
<td title='ct_tzra'>[% tr.ct_tzra %]</td>
<td title='count'>[% tr.count %]</td>
</tr>
[% END %]
</table>
</body></html>


$xsl=
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

        <xsl:output method="html"/>
        <xsl:template match="/">
                <xsl:element name='html'>
                <xsl:element name='body'>
                <xsl:element name="table">
                        <xsl:attribute name="id">results_table</xsl:attribute>
                        <xsl:attribute name="class">statstabledata sort-table</xsl:attribute>
                        <xsl:element name="thead">
                                <xsl:element name="tr">
                                        <xsl:element name="th">
                                                <xsl:text>ID</xsl:text>
                                        </xsl:element>
                                        <xsl:element name="th">
                                                <xsl:text>Patient Name</xsl:text>
                                        </xsl:element>
                                        <xsl:element name="th">
                                                <xsl:text>Appt Time</xsl:text>
                                        </xsl:element>
                                        <xsl:element name="th">
                                                <xsl:text>App Timezone</xsl:text>
                                        </xsl:element>
                                        <xsl:element name="th">
                                                <xsl:text>Timezone</xsl:text>
                                        </xsl:element>
                                        <xsl:element name="th">
                                                <xsl:text>Patient ID</xsl:text>
                                        </xsl:element>
                                        <xsl:element name="th">
                                                <xsl:text>Appt Phone </xsl:text>
                                        </xsl:element>
                                        <xsl:element name="th">
                                                <xsl:text>Appt Prov </xsl:text>
                                        </xsl:element>
                                        <xsl:element name="th">
                                                <xsl:text>Appt Location </xsl:text>
                                        </xsl:element>
                                        <xsl:element name="th">
                                                <xsl:text>Call Time </xsl:text>
                                        </xsl:element>
                                        <xsl:element name="th">
                                                <xsl:text>Timezone </xsl:text>
                                        </xsl:element>
                                        <xsl:element name="th">
                                                <xsl:text>Timezone </xsl:text>
                                        </xsl:element>
                                        <xsl:element name="th">
                                                <xsl:text>Count </xsl:text>
                                        </xsl:element>
                                </xsl:element>
                        </xsl:element>
                        <xsl:element name="tbody">
                                <xsl:for-each select="results/r">
                                        <xsl:element name="tr">
                                                <xsl:attribute name="onmouseover">
                                                        <xsl:text>_resp.tableSelect.rollOver(this);</xsl:text>
                                                </xsl:attribute>
                                                <xsl:attribute name="onmouseout">
                                                        <xsl:text>_resp.tableSelect.rollOut(this);</xsl:text>
                                                </xsl:attribute>
                                                <xsl:attribute name="ondblclick">
                                                        <xsl:text>_resp.tableSelect.dblclick(this);</xsl:text>
                                                </xsl:attribute>
                                                <xsl:attribute name="onclick">
                                                        <xsl:text>_resp.tableSelect.click({rowObject:this}, _resp.tableselect);</xsl:text>
                                                </xsl:attribute>
                                                <xsl:element name="td">
                                                <xsl:attribute name='title'>
                                                        <xsl:text>id</xsl:text>
                                                </xsl:attribute>
                                                        <xsl:value-of select="id"/>
                                                </xsl:element>
                                                <xsl:element name="td">
                                                <xsl:attribute name='title'>
                                                        <xsl:text>p_name</xsl:text>
                                                </xsl:attribute>
                                                        <xsl:value-of select="p_name"/>
                                                </xsl:element>
                                                <xsl:element name="td">
                                                <xsl:attribute name='title'>
                                                        <xsl:text>ap_time</xsl:text>
                                                </xsl:attribute>
                                                        <xsl:value-of select="ap_time"/>
                                                </xsl:element>
                                                <xsl:element name="td">
                                                <xsl:attribute name='title'>
                                                        <xsl:text>ap_tzr</xsl:text>
                                                </xsl:attribute>
                                                        <xsl:value-of select="ap_tzr"/>
                                                </xsl:element>
                                                <xsl:element name="td">
                                                <xsl:attribute name='title'>
                                                        <xsl:text>ap_tzra</xsl:text>
                                                </xsl:attribute>
                                                        <xsl:value-of select="ap_tzra"/>
                                                </xsl:element>
                                                <xsl:element name="td">
                                                <xsl:attribute name='title'>
                                                        <xsl:text>p_id</xsl:text>
                                                </xsl:attribute>
                                                        <xsl:value-of select="p_id"/>
                                                </xsl:element>
                                                <xsl:element name="td">
                                                <xsl:attribute name='title'>
                                                        <xsl:text>ap_phone</xsl:text>
                                                </xsl:attribute>
                                                        <xsl:value-of select="ap_phone"/>
                                                </xsl:element>
                                                <xsl:element name="td">
                                                <xsl:attribute name='title'>
                                                        <xsl:text>ap</xsl:text>
                                                </xsl:attribute>
                                                        <xsl:value-of select="ap"/>
                                                </xsl:element>
                                                <xsl:element name="td">
                                                <xsl:attribute name='title'>
                                                        <xsl:text>ap_loc</xsl:text>
                                                </xsl:attribute>
                                                        <xsl:value-of select="ap_loc"/>
                                                </xsl:element>
                                                <xsl:element name="td">
                                                <xsl:attribute name='title'>
                                                        <xsl:text>ct_time</xsl:text>
                                                </xsl:attribute>
                                                        <xsl:value-of select="ct_time"/>
                                                </xsl:element>
                                                <xsl:element name="td">
                                                <xsl:attribute name='title'>
                                                        <xsl:text>ct_tzr</xsl:text>
                                                </xsl:attribute>
                                                        <xsl:value-of select="ct_tzr"/>
                                                </xsl:element>
                                                <xsl:element name="td">
                                                <xsl:attribute name='title'>
                                                        <xsl:text>ct_tzra</xsl:text>
                                                </xsl:attribute>
                                                        <xsl:value-of select="ct_tzra"/>
                                                </xsl:element>
                                                <xsl:element name="td">
                                                <xsl:attribute name='title'>
                                                        <xsl:text>count</xsl:text>
                                                </xsl:attribute>
                                                        <xsl:value-of select="count"/>
                                                </xsl:element>
                                        </xsl:element>
                                </xsl:for-each>
                        </xsl:element>
                </xsl:element>
                </xsl:element>
                </xsl:element>
        </xsl:template>
</xsl:stylesheet>


