#!/usr/bin/perl -w

# Copyright 2020 Kevin Ryde

# This file is part of Math-PlanePath.
#
# Math-PlanePath is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3, or (at your option) any later
# version.
#
# Math-PlanePath is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with Math-PlanePath.  If not, see <http://www.gnu.org/licenses/>.


# Generate HTML list of the online man-pages.

use strict;
use warnings;
use sort 'stable';
use FindBin;
use App::Upfiles;
use File::Copy;
use File::Slurp ();
use File::Temp;
use File::chdir;
use File::stat ();
use Module::Util;
use HTML::Entities::Interpolate;
use POSIX ();
use Regexp::Tr;
use Sort::Key::Natural;

# uncomment this to run the ### lines
# use Smart::Comments;

my $webdir = "$ENV{HOME}/tux/web/math-planepath";
my $canonical_top = "https://user42.tuxfamily.org/math-planepath/";
my $out_filename = 'manpages.html';
my $author = "Kevin Ryde";
my $generator = $FindBin::Script;

chdir $webdir or die;
my $year = POSIX::strftime('%Y', localtime(time()));

# $n is a file size in bytes.
# Return a string which is a human-readable form, like "50 kbytes".
sub bytes_to_human {
  my ($n) = @_;
  if ($n <  1_000) { return "$n bytes"; }
  if ($n <  10_000) { return sprintf "%.1f kbytes", $n/1000; }
  if ($n <  1_000_000) { return sprintf "%.0f kbytes", $n/1000; }
  if ($n <  10_000_000) { return sprintf "%.1f mbytes", $n/1_000_000; }
  return sprintf "%.0f mbytes", $n/1_000_000;
}

# $n is an integer like 12500.
# Insert commas between thousands like "12,500".
sub number_commas {
  my ($n) = @_;
  while ($n =~ s/(\d)(\d{3})(,|$)/$1,$2/) {};
  return $n;
}

sub filename_to_module {
  my ($str) = @_;
  $str =~ s/\.html$//;
  $str =~ s/-/::/g;
  return $str;
}
CHECK { filename_to_module('Math-PlanePath.html') eq 'Math::PlanePath' or die; }

my @libdirs = (File::Spec->catdir($FindBin::Bin,
                                  File::Spec->updir,
                                  'lib'),
               File::Spec->catdir($FindBin::Bin,
                                  File::Spec->updir,
                                  File::Spec->updir,
                                  'pt',
                                  'lib'));
sub module_to_description {
  my ($module) = @_;
  my $filename = Module::Util::find_installed($module, @libdirs)
    // die "$module not found under @libdirs";
  my $str = File::Slurp::read_file($filename);
  $str =~ /=head1 NAME.*?-- (.*?)\n/s or die "$filename NAME not matched";
  return $1;
}

sub filename_sort_key {
  my ($str) = @_;
  $str = filename_to_module($str);
  $str =~ s/NumSeq/ZNumSeq/;  # sort last
  $str =~ s/PlanePath::Base/PlanePath::ZZZBase/;  # sort last
  return Sort::Key::Natural::mkkey_natural($str);
}

my @filenames = File::Slurp::read_dir('.');
@filenames = grep {! -d} @filenames;
@filenames = grep {/^[A-Z].*\.html$/} @filenames;
@filenames =sort {filename_sort_key($a) cmp filename_sort_key($b)} @filenames;
### @filenames
### num filenames: scalar(@filenames)

my $favicon = '';
if (-e "favicon.png") {
  $favicon = "\n<link rel=\"icon\" href=\"favicon.png\" type=\"image/png\"/>";
}

my $out = File::Temp->new;
my $dateModified = POSIX::strftime('%Y-%m-%d', gmtime(time()));

print $out <<"HERE";
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<!-- generated by $generator, DO NOT EDIT -->
<head>
<title>PlanePath Man Pages</title>
<meta name="description" content="Man pages of Math-PlanePath Perl modules.">
<meta name="Author" content="$Entitize{$author}">
<meta name="Generator" content="$Entitize{$generator}">$favicon
<meta name="viewport" content="width=device-width">
<link rel="canonical" href="$canonical_top$out_filename"/>
</head>
<body itemscope itemtype="http://schema.org/WebPage">
<meta itemprop="inLanguage" content="en"/>
<meta itemprop="dateModified" content="$dateModified"/>

<h1 align="center" itemprop="name">Math-PlanePath Man Pages (including Math-PlanePath-Toothpick)</h1>
<p>
(<a href="index.html">back to Math-PlanePath home page</a>)
HERE

my $count = 0;
my $total_bytes = 0;
my $join = "\n<p>";
my $prev_type = '';
foreach my $filename (@filenames) {
  $filename =~ /(Math-.*?-(Base)?)?/;
  my $type = $&;
  if ($type ne $prev_type) {
    print $out "<br>\n";
    $prev_type = $type;
  }

  my $bytes = -s $filename;
  $total_bytes += $bytes;
  my $st = File::stat::stat($filename);
  my $module = filename_to_module($filename);
  my $description = module_to_description($module);
  $module =~ s/^Math::PlanePath:://;  # shorten for display
  print $out $join,
    " <a href=\"$Entitize{$filename}\"><code>$Entitize{$module}</code></a>\n",
    "    -- $Entitize{$description}\n";
  $join = '<br>';
  $count++;

  # my $size = bytes_to_human(-s $filename);
  # (about $Entitize{$size})
}

# my $size_str = bytes_to_human($total_bytes);
# , about $size_str

print $out <<"HERE";
<p>
Total $count modules.
</p>

<hr width="100%">
<p>
<small>This page Copyright $year <span itemprop="copyrightHolder">$Entitize{$author}</span>.</small>
</p>

</body>
</html>
HERE

close $out or die;

my $old_content = File::Slurp::read_file($out_filename, {err_mode=>'quiet'})
  // '';
my $new_content = File::Slurp::read_file($out->filename);
foreach ($old_content, $new_content) {  # compare sans mod dates
  s/^<meta itemprop="dateModified".*//m;
  s/Copyright \d+//m;
}

my $diff;
if ($old_content eq $new_content) {
  $diff = 'unchanged';
} else {
  $diff = 'new      ';
  File::Copy::copy($out->filename, $out_filename);
}
my $bytes = -s $out_filename // '[undef]';
print "$diff $out_filename  $bytes bytes\n";

system 'weblint',$out_filename;
exit 0;
