#!/usr/bin/perl -w

# this can be used to annotate the entire QUIP distribution by doing
#  ./fix_headers `find . -type f -not -wholename "*fix_headers" -not -wholename "*.git*" -not -wholename "*quippy*" -not -wholename "*FoX-4.0.3*"  -print` > fix_headers.out 2>&1

my $usage=<<USAGE;
Replaces header strings with the appropriate header.
These can be of the form 
    <COMMENT_SYMBOL> HEADER[_SUFFIX] [POST_COMMENT_SYMBOL]
or
    <COMMENT_SYMBOL> H[HEADER_LABEL] <header line> [POST_COMMENT_SYMBOL]
inserted lines are of the form
    <COMMENT_SYMBOL> H[HEADER_LABEL] <header line> [POST_COMMENT_SYMBOL]

Header names, labels, and contents are specified below in the %headers hash.
hash key is the _SUFFIX (if any), content is an anonymous array
first array entry is HEADER_LABEL
second array entry is header text

code implicitly assumes that first line of inserted header is of the form
  <COMMENT_SYMBOL> H[HEADER_LABEL] X+ [POST_COMMENT_SYMBOL]
i.e. make sure all your headers start with a line of 'X' and nothing else
USAGE

use strict;

if ($#ARGV < 0) {
  die "Usage: $0 filename1 [filename2 ... ]\n\n$usage\n";
}
 
my %headers;
$headers{""} = ["H0", <<'H0text'];
==============================================================================

   libAtoms+QUIP: atomistic simulation library

   Portions of this code were written by

     Albert Bartok-Partay, Livia Bartok-Partay, Federico Bianchini,
     Anke Butenuth, Marco Caccin, Silvia Cereda, Gabor Csanyi, Alessio
     Comisso, Tom Daff, ST John, Chiara Gattinoni, Gianpietro Moras,
     James Kermode, Letif Mones, Alan Nichol, David Packwood, Lars
     Pastewka, Giovanni Peralta, Ivan Solt, Oliver Strickson, Wojciech
     Szlachta, Csilla Varnai, Steven Winfield.

   Copyright 2006-2015.

   These portions of the source code are released under the GNU General
   Public License, version 2, http://www.gnu.org/copyleft/gpl.html

   If you would like to license the source code under different terms,
   please contact Gabor Csanyi, gc121@cam.ac.uk

   Portions of this code were written by Noam Bernstein as part of
   his employment for the U.S. Government, and are not subject
   to copyright in the USA.


   When using this software, please cite the following reference:

   http://www.libatoms.org

==============================================================================
H0text

$headers{"_NO_DISTRIBUTION"} = ["HND", <<'HNDtext'];
==============================================================================

   libAtoms+QUIP: atomistic simulation library

   Portions of this code were written by

     Albert Bartok-Partay, Livia Bartok-Partay, Federico Bianchini,
     Anke Butenuth, Marco Caccin, Silvia Cereda, Gabor Csanyi, Alessio
     Comisso, Tom Daff, ST John, Chiara Gattinoni, Gianpietro Moras,
     James Kermode, Letif Mones, Alan Nichol, David Packwood, Lars
     Pastewka, Giovanni Peralta, Ivan Solt, Oliver Strickson, Wojciech
     Szlachta, Csilla Varnai, Steven Winfield.

   Copyright 2006-2015.

   Not for distribution

   Portions of this code were written by Noam Bernstein as part of
   his employment for the U.S. Government, and are not subject
   to copyright in the USA.

   When using this software, please cite the following reference:

   http://www.libatoms.org

==============================================================================
HNDtext

$headers{"_JAMES"} = ["HJ", <<'HJtext'];
==============================================================================

   libAtoms+QUIP: atomistic simulation library

   Portions of this code were written by
     Albert Bartok-Partay, Livia Bartok-Partay, Federico Bianchini,
     Anke Butenuth, Marco Caccin, Silvia Cereda, Gabor Csanyi, Alessio
     Comisso, Tom Daff, ST John, Chiara Gattinoni, Gianpietro Moras,
     James Kermode, Letif Mones, Alan Nichol, David Packwood, Lars
     Pastewka, Giovanni Peralta, Ivan Solt, Oliver Strickson, Wojciech
     Szlachta, Csilla Varnai, Steven Winfield.

   Copyright 2006-2015.

   These portions of the source code are released under the GNU General
   Public License, version 2, http://www.gnu.org/copyleft/gpl.html

   If you would like to license the source code under different terms,
   please contact Gabor Csanyi, gc121@cam.ac.uk

   Portions of this code were written by Noam Bernstein as part of
   his employment for the U.S. Government, and are not subject
   to copyright in the USA.


   When using this software, please cite the following reference:

   http://www.libatoms.org


==============================================================================
HJtext

$headers{"_LBFGS"} = ["HL", <<'HLtext'];
==============================================================================

   LBFGS

   This code was downloaded from J. Nocedal's web site
   URL: http://www.eecs.northwestern.edu/~nocedal/lbfgs.html

   Author: J. Nocedal

   Condition for Use:
     This software is freely available for educational or commercial 
     purposes. We expect that all publications describing work using this 
     software quote at least one of the references given below.  This 
     software is released under the GNU Public License (GPL)

   References:
     J. Nocedal. Updating Quasi-Newton Matrices with Limited Storage 
       (1980), Mathematics of Computation 35, pp. 773-782.
     D.C. Liu and J. Nocedal. On the Limited Memory Method for Large 
       Scale Optimization (1989), Mathematical Programming B, 45, 3, pp. 
       503-528.

==============================================================================
HLtext


$headers{"_QUIPPY"} = ["HQ", <<'HJtext'];
==============================================================================

   quippy: Python interface to QUIP atomistic simulation library

   Copyright James Kermode 2010-2015

   These portions of the source code are released under the GNU General
   Public License, version 2, http://www.gnu.org/copyleft/gpl.html

   If you would like to license the source code under different terms,
   please contact James Kermode, james.kermode@gmail.com

   When using this software, please cite the following reference:

   http://www.jrkermode.co.uk/quippy

==============================================================================
HJtext



foreach my $file (@ARGV) {
  if (-f $file) {
    warn "FILE $file\n";
    open FP, "<$file";
    my @l = <FP>;
    close FP;
    my $do = 1;
    my $f = join("", @l);

    my $found_header_content = 0;
    for my $header_name (keys(%headers)) {
      my $header_label = $headers{$header_name}->[0];
      if ($f =~ /^(.*\S+.+${header_label}.+X+.*)$/m) {
        my $l = $1;
        if ($l =~ /^\s*(\S+)\s+${header_label}\s+X+\s*(\S*)\s*$/m) {
          warn "got ${header_label}\n";
          my $pre = $1;
          my $post = (defined($2) ? $2 : "");
          replace_header ($f, $pre, $post, $headers{$header_name}->[1], "${header_label}");
          $found_header_content = 1;
        } else {
          warn "got $header_label, but couldn't parse header\n";
          $do = 0;
        }
      }
      last if ($found_header_content);
    }

    if (!$found_header_content) {
      if ($f =~ /^(.*HEADER.*)$/m) {
        my $l = $1;
        $l =~ /^\s*(\S+)\s+HEADER(_\S*)?\s*(\S*)\s*$/;
        my $pre = $1;
        my $header_type = (defined($2) ? $2 : "");
        my $post = (defined($3) ? $3 : "");
        warn "got HEADER${header_type} pre '$pre' post '$post'\n";
        if (exists($headers{$header_type})) {
          add_header($f, $pre, $post, $headers{$header_type}->[1], $headers{$header_type}->[0]);
        } elsif ($header_type eq "_CHECK") {
          $do = 0;
          warn "$file has CHECK header\n"
        } else {
          $do = 0;
          warn "unknown header type $header_type\n";
        }
      } else {
        $do = 0;
        warn "$file has no header\n"
      }
    }
    warn "do $do\n";
    if ($do) {
      ## warn "$f";
      rename("$file", "$file.bak");
      open FP, ">$file";
      print FP "$f";
      close FP;
    }
  }
}

exit 0;

sub add_header {
  my ($pre, $post, $header_text, $header_label) = ($_[1], $_[2], $_[3], $_[4]);
  $header_text =~ s/^/$pre $header_label /mg;
  if ($post ne "") {
    my @header_ls = split (/\n/, $header_text);
    my $max_line_len = 0;
    foreach my $l (@header_ls) {
      $max_line_len = (length($l) > $max_line_len ? length($l) : $max_line_len);
    }
    foreach my $l (@header_ls) {
      $l = sprintf("%-${max_line_len}s $post", $l);
    }
    $header_text = join("\n", @header_ls);
  }
  $_[0] =~ s/^\s*(\S+)\s+HEADER\s*(\S*)\s*$/$header_text/m;
}

sub replace_header {
  my ($f, $pre, $post, $header_text, $header_label) = @_;
  $f =~ s/^(\s*$pre\s+)${header_label}\s+X+(\s*$post\s*)$/$1HEADER$2/m;
  my @f = split(/\n/, $f);
  @f = grep { $_ !~ /^\s*$pre\s+${header_label}\s+.+\s*$post\s*$/ } @f;
  $f = join("\n", @f)."\n";
  add_header($f, $pre, $post, $header_text, "${header_label}");
  $_[0] = $f;
}
