package Gsg::Html;
use strict;
use warnings;
use Log::Log4perl qw(:easy);
use lib "/usr/local/lib";
use Shellex::Shellex qw(shellex findBin);
use Gsg::Gather qw(get_file_tree get_diff_stat);
use Gsg::MdParse qw (render_readme);
use Exporter qw(import);
our @EXPORT_OK = qw(
write_file append_file write_root_index clean_web_root
write_project_content
);

# These subs might belong in shellex
# Add logger for write opts TODO
sub write_file($$) {

my $content = shift;
my $path = shift;
open(my $fh, ">", $path) or die "Couldnt open $path\n";
print $fh "$content";
close $fh;

}

sub append_file($$) {
my $content = shift;
my $path = shift;
open(my $fh, ">>", $path) or die "Couldnt open $path\n";
print $fh "$content";
close $fh;
}

sub write_root_index($$$$) {

my $index = shift;
my $project_dirs_ref = shift;
my $web_projects_dir_path = shift;
my $logger = shift;
write_file("", $index);
append_file("<html><body><b>Git Projects</b><br><head><META NAME=\"ROBOTS\" CONTENT=\"NOINDEX, NOFOLLOW\"></head>\n",$index);
append_file("<small><i>Statically generated web root for browsing this git server</i></small><br>\n",$index);
my $date_cmd = findBin("date",$logger);
my $current_time = `$date_cmd`;
chomp $current_time;
append_file("<small><i>Generated at $current_time</i></small><br><hr/>\n",$index);

my $mkdirCmd = findBin("mkdir",$logger);
foreach my $project ( @$project_dirs_ref ) {
my $indexPath = $project . "index.html";
append_file("<table><div id=\"cotent\"><table id=\"index\"><tbody>\n",$index);
append_file("<tr><td><a href=\"projects/$indexPath\">$project</a></td>\n",$index);
shellex("$mkdirCmd -p $web_projects_dir_path$project",$logger);
}
append_file("</tr></tbody></table></div></body></html>\n",$index);
$logger->info("Wrote root index at $index");

}

sub check_for_html($) {

# Expects line from gen_line_nums or gen_diff_colors
# Will change < and > chars to < or >
# This adds tons of overhead, but should work better
# than <xmp> and will solve the rendering problems
my $line = shift;
my $new_line;
open my $fh, '>>', \$new_line or die "Can't open variable: $!";
foreach my $char ( split("",$line) ) {
if ( ! defined $char || $char eq "" ) {
print "Empty char\n";
next;
}

if ( $char eq "<" ) {
print $fh "<";
} elsif ( $char eq ">" ) {
print $fh ">";
} else {
print $fh "$char";
}
}

close $fh;
return $new_line;

}


sub gen_line_nums($$$) {

my $raw_file = shift;
my $filename = shift;
my $logger = shift;

my $html_file;
# Might be a better way to do this? TODO
open my $fh, '>>', \$html_file or die "Can't open variable: $!";

print $fh "<!DOCTYPE html><html><b>$filename</b><hr/><div id=\"content\"><pre id=\"blob\">";
my $line_counter = 1;
foreach my $line ( split("\n", $raw_file) ) {
if ( $line ne "" ) {
$line = check_for_html($line);
}
print $fh "<a href=\"\#l$line_counter\" class=\"line\" id=\"l$line_counter\">$line_counter</a>\t$line<br>";
$line_counter++;
}

print $fh "</pre></div><html>";
close $fh;

$logger->info("Generated line numbers for $filename");
return $html_file;

}

sub gen_raw_html($$$) {

my $raw_file = shift;
my $filename = shift;
my $logger = shift;

my $html_file;
# Might be a better way to do this? TODO
open my $fh, '>>', \$html_file or die "Can't open variable: $!";

print $fh "<!DOCTYPE html><html><div id=\"content\"><pre id=\"blob\">";
foreach my $line ( split("\n", $raw_file) ) {
if ($line ne "") {
$line = check_for_html($line);
}
print $fh "$line<br>";
}

print $fh "</pre></div><html>";
close $fh;

$logger->info("Generated HTML file for $filename");
return $html_file;

}

sub gen_diff_colors($$$) {

my $raw_diff = shift;
my $id = shift;
my $logger = shift;

my $html_diff;
open my $fh, '>>', \$html_diff or die "Can't open variable: $!";

#print $fh "<!DOCTYPE html><html><div id=\"content\"><pre id=\"blob\">";
print $fh "<!DOCTYPE html><html><b>$id</b><hr/><div id=\"content\"><pre>";
my $line_counter = 1;
foreach my $line ( split("\n", $raw_diff) ) {
if ( $line ne "" ) {
$line = check_for_html($line);
}

if ( $line =~ m/^\+/ ) {
print $fh "<font color=\"green\">$line</font><br>";
} elsif ( $line =~ m/^\-/ ) {
print $fh "<font color=\"red\">$line</font><br>";
} elsif ( $line =~ m/^@@/ ) {
print $fh "<font color=\"blue\">$line</font><br>";
} elsif ( $line =~ m/^diff/ ) {
print $fh "<font color=\"purple\">$line</font><br>";
} elsif ( $line =~ m/^commit/ ) {
print $fh "<font color=\"purple\"><b>$line</b></font><br>";
} else {
print $fh "$line<br>";
}
$line_counter++;
}

print $fh "</pre></div></html>";
close $fh;

$logger->info("Generated colored diff for $id");
return $html_diff;

}

# Main sub for generating project page
# Might make more sense to split into more subs?
sub write_project_content($$$$$) {

my $project_dirs_ref = shift;
my $trimmed_project_dirs_ref = shift;
my $web_projects_dir = shift;
my $clone_path = shift;
my $logger = shift;

# Make these array's easier to work with in a hash
# Key is path to actual git dir, val is path to associated web dir
my %projects_map;
@projects_map{@$project_dirs_ref} = @$trimmed_project_dirs_ref;
$logger->info("Assembling data structures of git info");

# Write files part of project index
foreach my $project_path ( keys %projects_map ) {
my $spec_web_dir = $web_projects_dir . $projects_map{$project_path};
my $project_index = $spec_web_dir . "index.html";
write_file("",$project_index);
append_file("<html><a href=\"../../index.html\"><b>Return to index</a></b><br>",$project_index);
my $uniq_clone_path = "Disabled";
if ( $clone_path ne "Disabled" ) {
$uniq_clone_path = $clone_path . $projects_map{$project_path};
}
append_file("<b><pre>Clone:<font color=\"green\"> git clone $uniq_clone_path</font></pre></b><hr/>",$project_index);
# Get all project data structures/info
my ( $file_tree_ref, $file_content_ref, $commits_ref, $commit_ids_ref ) = get_file_tree($project_path,$logger);

# Handle README
if ( grep /^README.md$/, keys %$file_content_ref ) {
$logger->info("$projects_map{$project_path} contains a README");
my $readme_html = render_readme(${$file_content_ref}{'README.md'},$logger);
append_file("$readme_html",$project_index);

}

append_file("<b>Files for $projects_map{$project_path}</b><br>",$project_index);
append_file("<hr/>",$project_index);
## Write files ##
append_file("<table><div id=\"cotent\"><table id=\"index\"><thead><tr><td><b>File</b></td><td><b>Commit</b></td><td><b>Raw</b></td></tr></thead><tbody>",$project_index);
foreach my $filename ( sort keys %$file_content_ref ) {
my $browserCompat = $filename . ".html";
my $browserCompatRaw = $filename . "_raw" . ".html";
# Rewrite dir paths so we can save on disk without producing actual dir structure
if ( $filename =~ m/\// ) {
my $copy = $filename;
$copy =~ s/\//_/g;
$browserCompat = $copy . ".html";
$browserCompatRaw = $copy . "_raw" . ".html";
}
append_file("<tr><td><a href=\"$browserCompat\">$filename</a></td><td>${$file_tree_ref}{$filename}</td><td><a href=\"$browserCompatRaw\">raw</a></td>",$project_index);
my $html_file = gen_line_nums(${$file_content_ref}{$filename},$filename,$logger);
write_file("$html_file",$spec_web_dir . $browserCompat);
my $raw_html_file = gen_raw_html(${$file_content_ref}{$filename},$filename,$logger);
write_file("$raw_html_file",$spec_web_dir . $browserCompatRaw);
}

append_file("</tr></tbody></table></div></body>",$project_index);
append_file("<br>", $project_index);

append_file("<html><b>Logs for $projects_map{$project_path}</b><br>",$project_index);
append_file("<table><div id=\"cotent\"><table id=\"index\"><tbody>",$project_index);
append_file("<hr/>",$project_index);

# iterate over array to keep ordering
foreach my $commit_id ( @$commit_ids_ref ) {
my $filename = $commit_id . ".html";
append_file("<tr><td><a href=\"$filename\">$filename</a></td>",$project_index);
my $html_diff = gen_diff_colors(${$commits_ref}{$commit_id},$commit_id,$logger);
write_file($html_diff,$spec_web_dir . $filename);
}
append_file("</tr></tbody></table></div></body>",$project_index);
append_file("</html>",$project_index);

}

$logger->info("Done writing files");

}

# Not used currently, need to do more trimming/etc
# TODO
# Work around is rm -rf the webroot manually and then just rerun gsg
sub clean_web_root($$$) {

my $web_projects_dir_path = shift;
my $git_projects_ref = shift;
my $logger = shift;
my $lsCmd = findBin("ls",$logger);
my $rmCmd = findBin("rm",$logger);

foreach my $dir ( split("\n", shellex("$lsCmd -d $web_projects_dir_path/*/",$logger)) ) {
if ( ! grep( /^$dir$/, @$git_projects_ref ) ) {
$logger->info("Found $dir in webroot but not in git root, removing...");
my $rmdir = $web_projects_dir_path . $dir;
$logger->info("Would remove $rmdir");
# Does this need to be safer? TODO
#shellex("$rmCmd $rmdir/*",$logger);
#shellex("$rmCmd -d $rmdir",$logger);
}
}

}


1;