
=head1 NAME

CFX5::PostHTMLReportConverter - Converts a Post HTML report to an ARZ report

=head1 SYNOPSIS

Utility class for Post HTML report conversion

=cut

package CFX5::PostHTMLReportConverter;

use strict;
use Cwd;
use File::Basename qw(basename dirname);
use File::Copy;
use File::Temp qw(tempfile);

use CFX5::Config qw(%Config);
use CFX5::Commands qw(do_cmd handle_rv);
use CFX5::CVFConverter qw(setup_viewer convert_cvf);
use CFX5::Output qw(:all);

sub dir_file {
    return join( '/', @_ );
}

sub new {

    my $class = shift;
    my $self  = {};
    bless $self, $class;

    $self->initialize(@_) or $self = undef;

    return $self;
}

sub initialize {

    my $self = shift;

    return 0 unless $self->get_7zip();

    $self->{local} = shift;

    $self->{meta}   = "<meta charset=\"UTF-8\">";
    $self->{title}  = [];
    $self->{style}  = [];
    $self->{script} = [];
    $self->{body}   = [];

    $self->{report_dir} = ".";
    $self->{image_dir}  = undef;

    $self->{images} = [];

    $self->{report_basename} = undef;
    $self->{report}          = [];

    $self->{zip_exe} = undef;

    1;
}

sub convert_report {
    my $self        = shift;
    my $report_name = shift;

    if ( !-e $report_name ) {
        return 0;
    }

    my $report_basename = basename($report_name);
    $report_basename =~ s/[.][[:alpha:]]+$//;
    $self->{report_basename} = $report_basename;

    return 0 unless $self->convert_html($report_name);
    $self->build_new_html();
    $self->process_images();
    $self->create_arz_report();
    $self->clean_up();

    1;
}

sub convert_html {

    my $self        = shift;
    my $report_name = shift;

    $self->{report_dir} = dirname($report_name);

    my $currentArray;
    my $currentTag = undef;

    if ( open( my $infh, '<', $report_name ) ) {

        while ( my $line = <$infh> ) {

            chomp $line;

            if ( not $currentTag ) {
                if ( $line =~ m/<style>/i ) {
                    $currentArray = \@{ $self->{style} };
                    $currentTag   = "style";
                }
                elsif ( $line =~ m/<title>/i ) {
                    $currentArray = \@{ $self->{title} };
                    $currentTag   = "title";
                }
                elsif ( $line =~ m/<script(?: +language=".*")?>/i ) {
                    $currentArray = \@{ $self->{script} };
                    $currentTag   = "script";
                }
                elsif ( $line =~ m/<body>/i ) {
                    $currentArray = \@{ $self->{body} };
                    $currentTag   = "body";
                }
            }

            if ( not $currentTag ) {
                next;
            }

            push @$currentArray, $line;
            if ( $line =~ m/<\/$currentTag\b/i ) {
                $currentTag = undef;
            }
        }
    }
    else {
        _error("Error reading $report_name: $!");
        return 0;
    }

    1;
}

sub get_report {

    my $self = shift;
    return ( join "\n", @{ $self->{report} } );
}

sub update_script {

    my $reportARZScript = << "__ARZ_SCRIPT__";

function showViewer( id, width, height, type, alttext, resPath ) {
  if( document.getElementById ) {
    if( imageRefObj.id != "-1" ) {
      showPicture( imageRefObj.id, imageRefObj.width, imageRefObj.height,
		   imageRefObj.type, imageRefObj.alttext, imageRefObj.resPath );
    }
    imageRefObj = new ImageRef( id, type, width, height, alttext, resPath );

    x = document.getElementById( id );
    var text =
      '<table class=FigureTable><TR><TD class=Figure3D>'
      +'<div name=' + id + ' id="3DViewer"'
      +' style="width:' + width + '; height:' + height + ';">'
      +'</div>\\n'
      +'</TD><TD class=FigureClose3D>\\n'
      +'<a href="javascript:showPicture(\\'' + id + '\\', ' + width + ', ' + height
      + ', \\'' + type + '\\', \\'' + alttext + '\\', \\'' + resPath + '\\')">\\n'
      +'<img src="' + resPath + 'Close3DViewer.png" border=0 title="Close 3D Viewer">\\n'
      +'</a>'
      +'</TD></TR></table>';
    x.innerHTML = '';
    x.innerHTML = text;
    var v = require('gltfviewer');
    var i = new v("3DViewer", id + '.avz', "FILE", null, {report: true, showAbout: false, showFileOpen: false});
  }
}

__ARZ_SCRIPT__

    my $self = shift;

    my $str = join( "\n", @{ $self->{script} } );

    $str =~ s/(<script)\s*.*?>/$1>/ig;
    $str =~ s/function\s+showViewer
              \s*[(]\s*id,\s*width,\s*height,\s*type,\s*alttext,\s*resPath\s*[)]\s*
              ({ (?> [^{}]++ | (?1) )*+ }) # recursive pattern search for {}
             /
              $reportARZScript
             /xge;

    @{ $self->{script} } = split "\n", $str;
}

sub update_body {

    my $self = shift;
    my $str = join( "\n", @{ $self->{body} } );

    $str =~ s/<a\s*name\s*=/<a id=/g;

    @{ $self->{body} } = split "\n", $str;
}

sub collect_images {

    my $self = shift;

    my $images = \@{ $self->{images} };

    for my $line ( @{ $self->{body} } ) {

        if ( $line =~ m/<img src *= *'.*'/ ) {
            my @src = $line =~ m/^.*<img src *= *'([^']+)'.*$/g;
            if (@src) {
                push @$images, $src[0];
            }
        }
    }

    my $image_dir = \$self->{image_dir};

    if (@$images) {

        if ( not $$image_dir ) {
            $$image_dir = dirname( $$images[0] );
        }

        if ( $$image_dir =~ m/[^.]+/ ) {
            if ($$image_dir) {
                my $dir_path = $$image_dir;
                for my $line ( @{ $self->{body} } ) {
                    $line =~ s|\b$dir_path([\\/]+)([^/\\])|$2|eg;
                }
            }
        }
    }

    my $close_image_file = "Close3DViewer.png";
    if ($$image_dir) {
        push @$images, dir_file( $$image_dir, $close_image_file );
    }
    else {
        push @$images, $close_image_file;
    }

    my $report_path = $self->{report_dir};

    if ( $report_path && $report_path !~ m|^ *[.][\\/]?$| ) {
        for my $image ( @$images ) {
            $image = dir_file( $report_path, $image );
        }
    }
}

sub convert_cvfs {

    my $self      = shift;
    my @cvf_files = @_;

    my $rv = setup_viewer( $self->{local} );
    if ( not $rv ) {
        convert_cvf(@cvf_files);
    }

    1;
}

sub process_images {

    my $self = shift;

    my $images = \@{ $self->{images} };

    if (@$images) {

        my $arz_temp_dir = $self->get_temp_dir;

        my @cvf_files;

        for my $image (@$images) {

            File::Copy::copy( $image, $arz_temp_dir );

            $image =~ s/[.][[:alpha:]]+$/.cvf/;

            if ( -e $image ) {
                File::Copy::copy( $image, $arz_temp_dir );
                push @cvf_files, dir_file( $arz_temp_dir, basename($image) );
            }
        }

        if (@cvf_files) {

            $self->convert_cvfs(@cvf_files);
            for my $f (@cvf_files) {
                unlink($f);
            }
        }

    }
}

sub build_new_html {

    my $self   = shift;
    my $report = \@{ $self->{report} };

    $self->update_script();
    $self->update_body();
    $self->collect_images();

    push @$report, "<html>\n";
    push @$report, "<head>\n";
    push @$report, $self->{meta};
    push @$report, @{ $self->{title} };
    push @$report, @{ $self->{style} };
    push @$report, @{ $self->{script} };
    push @$report, @{ $self->{body} };
    push @$report, "</head>\n";
    push @$report, "</html>\n";
}

sub get_temp_dir {

    my $self = shift;

    my $arz_temp_dir = \$self->{arz_temp_dir};

    if ( not( $$arz_temp_dir && -e $$arz_temp_dir ) ) {
        $$arz_temp_dir = "arzTempDir_" . $$;
        mkdir $$arz_temp_dir, 0755;
    }

    return $$arz_temp_dir;
}

sub create_arz_report {

    my $self = shift;

    my $report_basename = $self->{report_basename};

    my $new_html_report = $report_basename . ".html";

    $new_html_report = dir_file( $self->get_temp_dir(), $new_html_report );

    my ( $outfh, $outfilename ) = tempfile();
    my $new_report = $self->get_report();
    print $outfh $new_report;

    close $outfh;

    move( $outfilename, $new_html_report );

    my $arz_report = $report_basename . ".arz";

    my $current_dir = getcwd();

    chdir( $self->get_temp_dir() );

    my @runwith;

    my @args = ( "-tzip", "-sdel", "-y", "a", "$arz_report", "*.*" );

    my $rv = handle_rv( do_cmd( @runwith, $self->get_7zip(), @args ) );

    if ( not $rv ) {
        move( $arz_report, "../" );
    }

    chdir($current_dir);

}

sub get_7zip {

    my $self    = shift;
    my $zip_exe = \$self->{zip_exe};

    if ( not $$zip_exe ) {

        my $ansys_7zip=$Config{CFX_7ZIP_EXE};

        if ( -e $ansys_7zip ) {
            $$zip_exe = $ansys_7zip;
        } else {
            _error("File '$ansys_7zip' does not exist.");
        }
    }

    if ( not $$zip_exe ) {
        _error(
"Unable to locate 7-Zip. ANSYS Report File (arz) generation requires 7-Zip to be installed."
        );
    }

    return $$zip_exe;
}

sub clean_up {
    my $self = shift;
    rmdir( $self->{arz_temp_dir} );
}

1;

__END__
