#!/usr/bin/perl

use File::stat;
use strict;

if(@ARGV == 0){
  process_stream(\*STDIN,\*STDOUT);
  exit(0);
}

if($ARGV[0] eq '-h' || @ARGV > 2){
  #The one and only command line option.
  print("Converts gemtext to HTML.\n  gmi2html.pl <infile.gmi> <outfile.html>\n\n");
  print("If used with no arguments, defaults to converting stdin to stdout.\n\n");
  print("If used with one argument, which must be a gmi file, will write to a corresponding html file.\n");
  print("If used with two arguments, will convert gemtext in the first file to HTML in the second.\n\n");
  print("Links to .gmi files will be changed to .html unless they use the gemini:// protocol descriptor.\n");
  print("Links to image files will be converted to img tags.\n");
  exit(0);
}

my $infile = $ARGV[0];
if(! -f $infile){
  print STDERR "Input file $infile not found.\n";
  exit(1);
}

my $outfile;

if(@ARGV == 1){
  #Single file mode.
  if(!($infile =~ m/\.gmi$/i)){
    print STDERR "Input file must end with extension .gmi (run with -h for more information.\n";
    exit(1);
  }
  $outfile = $infile;
  $outfile =~ s/\.gmi$/\.html/i;
}

if(@ARGV == 2){
  $outfile=$ARGV[1];
}

if(@ARGV != 0){
  if(!($outfile =~ m/\.html?$/i)){
    print STDERR "Output file must end with extention .html or .htm (This is to prevent accidential overwriting).\n";
    exit(1);
  }
}
print STDERR "$infile -> $outfile\n";

open(my $infh, "<:encoding(utf-8)", $infile) || die "Failed to open input file $infile";
open(my $outfh, ">:encoding(utf-8)", $outfile) || die "Failed to open input file $outfile";
#print STDERR "Processing.\n";
process_stream($infh, $outfh);
close($infh);
close($outfh);

sub process_stream($$){
  my $instream=$_[0];
  my $outstream=$_[1];
  my @htmlout; #The only reason this can't be done stream-to-stream is the title tag!

  my $ul=0; #Are we in a bulleted list?
  my $bc=0; #Are we in a blockquote?
  my $title;
  push(@htmlout, "\n</head>\n<body>\n");
  while(<$instream>){
    s/[\r\n]//g;
    s/\&/\&amp;/g;
    s/</\&lt;/g;
    s/>/\&gt;/g;
    if($_ eq '```'){ #Blockquote toggle
      if($bc){
        push(@htmlout, "</pre>\n");
      }else{
        push(@htmlout, "<pre>\n");
      }
      $bc=!$bc;
      next;
    }
    if($bc){
      push(@htmlout, "$_\n");
      next;
    }
    if($_ =~ m/^\w*$/){ #Empty lines are meaningless in HTML.
      next;
    }
    if(!$ul && substr($_, 0, 2) eq '* '){ #Handling for unordered lists.
      push(@htmlout, "<ul>\n");
      $ul=1;
    }
    if($ul && !(substr($_, 0, 2) eq '* ')){
      push(@htmlout, "</ul>\n");
      $ul=0;    
    }    
    if($ul){
      $_=substr($_, 2);
      push(@htmlout, "<li>$_</li>\n");
      next;
    }
    if(substr($_, 0, 4) eq '### '){
      push(@htmlout, "<h3>".substr($_, 4)."</h3>\n");
    }elsif(substr($_, 0, 3) eq '## '){
      push(@htmlout, "<h2>".substr($_, 3)."</h2>\n");
    }elsif(substr($_, 0, 2) eq '# '){
      push(@htmlout, "<h1>".substr($_, 2)."</h1>\n");
      if(!$title){
        $title=substr($_, 2);
      }
    }elsif(substr($_, 0, 6) eq '=&gt; '){
      my $link=substr($_, 6);
      my $space=index($link, ' ');
      #$link =~ m/([^ ]+) +(.+)/;
      my $a=substr($link, 0, $space);
      my $b=substr($link, $space+1);
      my $isimage=0;
        if( $a =~ m/\.jpg$/i ||
            $a =~ m/\.png$/i ||
            $a =~ m/\.webp$/i ||
            $a =~ m/\.gif$/i ||
	    $a =~ m/\.svg$/i ||
            $a =~ m/\.avif$/i) {
          $isimage=1;
        }
      if($isimage){
	push(@htmlout, '</div>');
        push(@htmlout, '<img src="'.$a.'" alt="'.$b."\"><br>\n");
	push(@htmlout, '<div class="contentbox">');
      }else{
	if(substr($a, 0, 9) ne 'gemini://'){
	  $a =~ s/\.gmi$/\.html/i;
	}
        push(@htmlout, '<a href="'.$a."\">$b</a><br>\n");
      }
    }else{
      push(@htmlout, "<p>$_</p>\n");
    }
  }
  print $outstream "<!DOCTYPE HTML>\n<html>\n<head>\n";
  if($title){
  print $outstream "<title>$title</title>\n";
  }
  print $outstream '<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta charset="utf-8">';
  print $outstream '<style>
h1 {
  text-align: center;
}
h2,h3 {
  padding-left:1em;
}
img {
  max-width:100%;
  text-align: center;
  margin:auto;
  display:block;
}
.contentbox {
  max-width:60em;
  margin: auto;
  padding-left: 2em;
  padding-right: 2em;
  padding-top: 0.5em;
  padding-bottom: 0.5em;
}
p {
  text-align: justify;
}
</style>'; 
  print $outstream "</head><div class=\"contentbox\">";
  while(my $line=shift(@htmlout)){
    print $outstream $line;
  }
  print $outstream "</div>\n</body>\n</html>";
}
