#!/usr/bin/perl
# Project: Split an faa weather brief into messages
# Copyright: This package is licensed under the terms of
#            GNU GENERAL PUBLIC LICENSE Version 2, June 1991
#            You should have received a copy with this package.
# Author:  Dr. Robert J. Meier, Jr.
# History: 00-07-27 -rjm- file creation



#
# Constants
#

# Identification
$name      = "parseduat";
$NAME      = "PARSEDUAT";

# Platform dependencies
$DS        = "/";		# Directory separator
$DSR       = "\\/";		# Directory separator regexp

# DUAT parse strings
$acsection = "ADVERSE CONDITIONS";
$mesection = "CURRENT CONDITIONS";
$messub    = "SPECI";
$fasection = "FORECAST CONDITIONS";
$fawsub    = "WINDS ALOFT FORECASTS";
$faasub    = "[^\\s]+\\s+AMD";
$ntsection = "NOTICE TO AIRMEN \\(NOTAMS\\)";
$ntgsub    = "GENERAL FLIGHT DATA CENTER NOTAMS";
$ntgfsub   = "^FDC\\s+[^\\s]+\\s+[^\\s]+.*";
$ntasub    = "ATC DELAYS AND ADVISORIES";
$ntaasub   = "^ATCSCC\\s+ADVZY.*";



#
# Includes
#
require "getopts.pl";		# &Getopts()



#
# Global variables
#

# Default the execution parameters
$error       = 0;		# Assume success
$config      = "";		# Assume no config file
$incabs      = 0;		# Include directory in include directive
$html        = 0;		# Generate html
$filetype    = "";		# Default file type
$rootname    = "";		# Default file root

# File state
$dir         = "";		# relative directory
$prefix      = "";		# file distinguisher
$level       = 0;		# create directories level
$top         = "";		# top level
@prefixstack = ();		# prefix stack
@filestack   = ();		# filename stack



#
# Support routines
#

# Select top file name
sub TopFileName {
  open(DATE, "date +duat-session-%y%m%d |") || die "Unable to execute date: $!";
  local($date) = <DATE>;
  close DATE;
  chomp $date;
  $date .= ".$filetype" if "" ne "$filetype";
  $date;
}

# Select a config file name
sub ConfigFileName {
  if ("" ne "$opt_f") {
    $opt_f;
  } elsif ("" ne $ENV{"$NAME"."RC"}) {
    $ENV{"$NAME"."RC"};
  } elsif (-r $ENV{"HOME"}."$DS.$name"."rc") {
    $ENV{"HOME"}."$DS.$name"."rc";
  } elsif (-r $DS."etc$DS$name$DS$name"."rc") {
    $DS."etc$DS$name$DS$name"."rc";
  } elsif (-r $DS."opt$DS$name$DS"."etc$DS$name"."rc") {
    $DS."opt$DS$name$DS"."etc$DS$name"."rc";
  } else {
    "";
  }
}

# Read a config file
sub ReadConfigFile {
  local($config) = @_;
  if (-r "$config") {
    open(CONFIG, "$config") || die "Unable to read configuration, $config: $!";
    local($ignore, $delim) = split(//, <CONFIG>);
    while (<CONFIG>) {
      print STDERR "$config:$_" if $opt_v;
      chomp;
      local($record) = split(/$ignore/);
      local(@field) = split(/$delim/, $record);
      $dir      = $field[1] if $field[0] =~ /ROOT_DIRECTORY/i;
      $top      = $field[1] if $field[0] =~ /TOP_FILE/i;
      $level    = $field[1] if $field[0] =~ /CREATE_DIRECTORIES_LEVEL/i;
      $incabs   = 1         if $field[0] =~ /INCLUDE_DIRECTORIES_IN_DIRECTIVE/i;
      $html     = 1         if $field[0] =~ /GENERATE_HTML/i;
      $rootname = $field[1] if $field[0] =~ /ROOT_NAME/i;
      $filetype = $field[1] if $field[0] =~ /FILE_TYPE/i;
    }
  }
}

# Open a new file
sub PushFile {
  local($file, $parent) = @_;
  if ("" ne "$parent") {
    $prefix .= $parent;
    if ($level < scalar(@prefixstack)) {
      $prefix .= ".";
    } elsif ("" eq "$dir") {
      !system("mkdir -p \"$prefix\"") || die "Unable to mkdir $prefix: $!";
      $prefix .= $DS;
    } else {
      !system("mkdir -p \"$dir$DS$prefix\"") || die "Unable to mkdir $dir$DS$prefix: $!";
      $prefix .= $DS;
    }
  }
  $name = $file;
  if ($file =~ /^$DSR/) {
  } elsif ("" eq "$dir") {
    $name = "$prefix$file";
  } else {
    $name = "$dir$DS$prefix$file";
  }
  if (-e "$name") {
    $name =~ s/\.([^\.]*)$//;
    $name .= ".$..$1";
  }
  local($incname) = $name;
  if ($incabs) {
  } elsif ($level < scalar(@prefixstack)) {
    $incname =~ s/[^$DSR]*$DSR//g;
  } elsif ("" eq "$parent") {
    $incname =~ s/[^$DSR]*$DSR//g;
  } else {
    $incname =~ s/[^$DSR]*$DSR//g;
    $incname = "$parent$DS$incname";
  }
  if ($html) {
    print OUT "<A HREF=\"$incname\">$incname</A>\n";
  } else {
    print OUT "#include \"$incname\"\n";
  }
  close OUT;
  unshift(@prefixstack, "$prefix");
  unshift(@filestack, "$name");
  print STDERR (">"x scalar(@filestack))."$name\n" if $opt_v;
  (! -e "$name") || die "$name already exists";
  open(OUT, ">$name") || die "Unable to open for write, $name: $!";
  if ($html) {
    print OUT "<HTML><HEAD><TITLE>DUAT:$incname</TITLE></HEAD>\n";
    print OUT "<BODY><PRE>";
  }
}

# Close a file
sub PopFile {
  if ($html) {
    print OUT "</PRE></BODY></HTML>\n";
  }
  close OUT;
  $prefix = shift(@prefixstack);
  $name = shift(@filestack);
  print STDERR "<".("<"x scalar(@filestack))."$name\n" if $opt_v;
  open(OUT, ">>$name") || die "Unable to open for append, $name: $!";
}

# Close files to a specified Depth
sub PopFiles {
  local($depth) = @_;
  $depth = 0 if 0 > $depth;
  if ($depth < scalar(@filestack)) {
    if ($html) {
      print OUT "</PRE></BODY></HTML>\n";
    }
    close OUT;
    local($name);
    while ($depth < scalar(@filestack)) {
      shift(@prefixstack);
      $name = shift(@filestack);
      print STDERR "<".("<"x scalar(@filestack))."$name\n" if $opt_v;
    }
    if (0 < scalar(@filestack)) {
      $prefix = $prefixstack[0];
      $name = $filestack[0];
      open(OUT, ">>$name") || die "Unable to open for append, $name: $!";
    }
  }
}

# Remove invalid characters from a filename
sub SafeFilename {
  local($name) = @_;
  $name =~ s/[\s\:$DSR]/_/g;
  $name;
}



#
# Main program
#

# Process the command-line options
$error = -1 if !&Getopts('hvif:d:e:r:l:t:');

# Read the configuration file
$config = &ConfigFileName();
&ReadConfigFile($config);

# Validate the command-line options
$dir      = $opt_d if "" ne "$opt_d";
$filetype = $opt_e if "" ne "$opt_e";
$html     = $opt_h if "" ne "$opt_h";
$incabs   = $opt_i if "" ne "$opt_i";
$level    = $opt_l if "" ne "$opt_l";
$rootname = $opt_r if "" ne "$opt_r";
$top      = $opt_t if "" ne "$opt_t";
$filetype = $html ? "html" : "txt"            if "" eq "$filetype";
$rootname = $html ? "index.html" : "root.txt" if "" eq "$rootname";
$top      = &TopFileName()                    if "" eq "$top";


# If the command-line arguments are invalid, indicate usage
if ($error) {
  print STDERR "Usage:$0 [-v] [-f file] [-d dir] [-l level] [-i]\n";
  print STDERR "    [-r file] [-e filetype] [-t file] [file...]\n";
  print STDERR "  -d root directory     [$dir]\n";
  print STDERR "     ROOT_DIRECTORY\n";
  print STDERR "  -e file type          [$filetype]\n";
  print STDERR "     FILE_TYPE\n";
  print STDERR "  -f configuration file [$config]\n";
  print STDERR "  -i dirs in include    [$incabs]\n";
  print STDERR "     INCLUDE_DIRECTORIES_IN_DIRECTIVE\n";
  print STDERR "  -l create dir level   [$level]\n";
  print STDERR "     CREATE_DIRECTORIES_LEVEL\n";
  print STDERR "  -r directory top file [$rootname]\n";
  print STDERR "     ROOT_NAME\n";
  print STDERR "  -t root file          [$top]\n";
  print STDERR "     TOP_FILE\n";
  print STDERR "  -v verbose            [$opt_v]\n";

# Break an duat brief into sections
} else {

  &PushFile(&SafeFilename("$top"), "");
  # Read the input file
  while (<>) {
    chomp;

    # Major section starts
    if (/^===>([^\<]*).*/) {
      print STDERR "===>\n" if $opt_v;
      $section = $1;
      &PopFiles(1);
      &PushFile(&SafeFilename("$rootname"), &SafeFilename("$section"));
    }

    # Duat session settings
    elsif (/^===.*/) {
      print STDERR "===\n" if $opt_v;
      &PopFiles(1);
    }

    # Adverse conditions
    elsif ($section =~ /$acsection/) {
      if (/^   ([^ ].*)/) {
	print STDERR "   $section\n" if $opt_v;
	$subsection = $1;
	&PopFiles(2);
	&PushFile(&SafeFilename("$rootname"), &SafeFilename("$subsection"));
      }
    }

    # Current conditions
    elsif ($section =~ /$mesection/) {
      if (/^   ([^ ].*)/) {
	print STDERR "   $section\n" if $opt_v;
	$subsection = $1;
	&PopFiles(2);
	&PushFile(&SafeFilename("$rootname"), &SafeFilename("$subsection"));
      } elsif (/^([^\s]+\s+[^\s]+\s+[^\s]+)/) {
	$message = "$1";
	if ($message =~ /^$messub/) {
	} else {
	  &PopFiles(3);
	  print STDERR "current: $message\n" if $opt_v;
	  &PushFile(&SafeFilename("$message.$filetype"), "");
	}
      }
    }

    # Forecast conditions
    elsif ($section =~ /$fasection/) {
      if ($subsection =~ /$fawsub/) {
      } elsif (/^   ([^ ].*)/) {
	print STDERR "   $section\n" if $opt_v;
	$subsection = $1;
	&PopFiles(2);
	&PushFile(&SafeFilename("$rootname"), &SafeFilename("$subsection"));
      } elsif (/^([^\s]+\s+[^\s]+\s+[^\s]+\s+[^\s]+)/) {
	$message = "$1";
	if ($message =~ /$faasub/) {
	} else {
	  &PopFiles(3);
	  print STDERR "forecast: $message\n" if $opt_v;
	  &PushFile(&SafeFilename("$message.$filetype"), "");
	}
      }
    }

    # Notams
    elsif ($section =~ /$ntsection/) {
      if ($subsection =~ /$ntgsub/) {
	if (/($ntgfsub)/) {
	  $message = "$1";
	  &PopFiles(3);
	  print STDERR "general fdc notam: $message\n" if $opt_v;
	  &PushFile(&SafeFilename("$message.$filetype"), "");
	} elsif (/^   $ntasub/) {
	  $subsection = $ntasub;
	  &PopFiles(2);
	  print STDERR "   $subsection\n" if $opt_v;
	  &PushFile(&SafeFilename("$rootname"), &SafeFilename("$subsection"));
	}
      } elsif ($subsection =~ /$ntasub/) {
	if (/($ntaasub)/) {
	  $message = "$1";
	  &PopFiles(3);
	  print STDERR "atc advisory: $message\n" if $opt_v;
	  &PushFile(&SafeFilename("$message.$filetype"), "");
	}
      } elsif (/^   ([^ ].*)/) {
	$subsection = $1;
	&PopFiles(2);
	print STDERR "   $subsection\n" if $opt_v;
	&PushFile(&SafeFilename("$rootname"), &SafeFilename("$subsection"));
      } elsif (/^([^\s]+\s+[^\s]+)/) {
	$message = "$1";
	&PopFiles(3);
	print STDERR "notam: $message\n" if $opt_v;
	&PushFile(&SafeFilename("$message.$filetype"), "");
      }
    }

    # Write the output
    print OUT "$_\n";
  }
  &PopFiles(0);
}
