#!/usr/bin/env perl
#
#  $Id: 5e7076d6a02c7ddd9db87955511d4f1863bcad44 $
#
#  Convert conf files to Asciidoc
#
#
use File::Basename;
use File::Spec;
use Getopt::Std;

$was_raw = 0;
$raw = 0;
$blank = 0;
$print_code = 0;

getopts('a:c:o:t');

$script_dir = dirname(__FILE__);
$filename = "$script_dir/links.txt";

$opt_c = 0 if (defined $opt_t) ;

$print_code = $opt_c;

%links = {};

#
#  Read the links file.
#
#  @todo - have this script take multiple inputs, so that we don't
#  have to read the links file on every file we convert.
#
open FILE, "<$filename" or die "Failed to open $filename: $!\n";
while (<FILE>) {
	chop;
	($name, $link) = split;

	$links{$name} = $link;
}
close FILE;

$links{"sites-available/"} = "$opt_a/sites-available/index.adoc";
$links{"mods-available/"} = "$opt_a/mods-available/index.adoc";

sub process_file {
	my $input = shift;
	my $output_file = shift;
	my @code = ();

	if (!defined $output_file) {
	    $output = STDOUT;
	} else {
	    open $output, ">$output_file" or die "Failed creating $output_file: $!\n";
	}

	while (<$input>) {
		#
		#  Skip editor commands
		#
		if (/^#\s*-\*- text -\*-/) {
			next;
		}

		#
		#  Need the [:] to avoid git getting excited
		#
		if (/\$Id[:] /) {
			next;
		}

		# Skip ###### banners
		if (/^##+$/) {
			next;
		}

		# Print one line of blank text, but suppress multiple blank lines.
		if (/^\s*$/) {
			print $output "\n" if (!$blank);
			$blank = 1;
			next;
		}

		$blank = 0;

		undef $prefix;

		#
		#  Commented-out config blocks get converted to commented out raw text.
		#
		if (/^#[\t]/ || /^#[^\s]/) {
			$raw = 1;
		#	print "R";

		#
		#  Comments in the configuration files get converted to plain
		#  text.
		#
		} elsif (/^\s*#/) {
			s/^\s*#[\t ]{0,2}//;

			#	print "T";

			#
			#  Ensure that lists get formatted correctly
			#
			if (/^\s*\*/) {
				$prefix = "  ";
			}

			$raw = 0;
		} else {
			$raw = 1;

		#	print "C";
		}

		if ($raw != $was_raw) {
			print $output "```\n" if ($print_code);
			$was_raw = $raw;
		}

		print $output $prefix if defined $prefix;

		$line = $_;

		my @words = split;

		#
		#  See if we can automagically make cross-links
		#
		foreach $word (@words) {
			next if ($word eq '\`\`\`');

			next if ($word !~ /.*`(.+?)`.*/);

			$key = $1;

			#
			#  @todo - automatically add cross-links for:
			#
			#	mods-available/
			#	sites-available/
			#
			#  etc.
			#
			if ($key =~ /^mods-available\/./) {
				$links{$key} = "$opt_a/$key.adoc";
			}
			elsif ($key =~ /^sites-available\/./) {
			    	$links{$key} = "$opt_a/$key.adoc";
			}

			#
			#  A bare `eap` gets converted to a reference to the EAP
			#  module, if the EAP module exists.
			#
			if (!$links{%key} && -e "$opt_a/../raddb/mods-available/$key") {
				$links{$key} = "$opt_a/mods-available/$key.adoc";
			}

			next if (!$links{$key});

			if ($links{$key} =~ /^http/) {
				$link = "`link:" . $links{$key} . "[" . $key . "]`";

			} elsif ($links{$key} =~ /^$opt_a/) {
				#
				#  Link to the *relative* path for the file.
				#  Note that we're passed "-a foo/doc/raddb",
				#  and also an output file of "doc/raddb/bar.adoc"
				#  So we need to strip out the duplicate directories.
				#
				my $absdir = dirname($opt_a . "/" . $output_file);
				$absdir =~ s,doc/raddb/,/,;

				my $relative = File::Spec->abs2rel($links{$key}, $absdir);

				$link = "link:" . $relative . "[" . $key . "]";

			} else {
				$link = "<<" . $links{$key} . "," . $key . ">>";
			}

			#
			#  Yes, this is terrible.  We should really just print each
			#  word individually, but that would also mess up (mildly)
			#  whitespace.
			#
			$line =~ s/`\Q$key`/$link/g;
		}

		#
		#  Auto-link to RFCs
		#
		if ($line =~ s,Section ([^ ]+) of RFC (\d+),https://tools.ietf.org/html/rfc${2}#section-${1}\[Section $1 of RFC $2\],g) {
			# nothing
	    } elsif ($line =~ s,RFC (\d+) Section ([\d\.]+),https://tools.ietf.org/html/rfc${1}#section-${2}\[RFC $1 Section $2\],g) {
			# and again nothing!
		} else {
			$line =~ s,RFC (\d+),https://tools.ietf.org/html/rfc${1}\[RFC $1\],g;
		}

		$line =~ s,doc/antora/modules/([^/]+)/pages/(.*)/([^/]+).adoc,xref:$1:$2/$3.adoc[$3],g;

		if (!$print_code) {
		    if ($raw && $was_raw) {
			push @code, $line if ($opt_t);
			next;
		    }
		}

		#
		#  And print out the raw text.
		#
		print $output $line;
	}

	#
	#  Terminate any trailing "raw" text.
	#
	print $output "```\n" if ($print_code);

	if ($opt_t) {
	    print $output "\n";
	    print $output "== Default Configuration\n\n";

	    print $output "```\n";

	    foreach $line (@code) {
		print $output $line;
	    }

	    print $output "```\n";
	}
}

sub HELP_MESSAGE {
	print "usage: conf2adoc [opts]\n";
	print "    -a <directory>\tthe root directory for Asciidoc conversion.\n";
	print "    -o <filename>\tthe output filename.\n";
	exit 0;
}

if (!defined $opt_a) {
	$opt_a = "";
}

process_file(STDIN, $opt_o);
