#! /usr/bin/perl -w
    eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
        if 0; #$running_under_some_shell

use strict;
use File::Find ();
use File::Basename;

# Set the variable $File::Find::dont_use_nlink if you're using AFS,
# since AFS cheats.

# for the convenience of &wanted calls, including -eval statements:
use vars qw/*name *dir *prune/;
*name   = *File::Find::name;
*dir    = *File::Find::dir;
*prune  = *File::Find::prune;

#sub wanted;

sub Usage {
    die "Usage: add-licenses dir [exclude.txt]\n";
}

my $DOUPDATES = 1;

my @files = ();
my %exclude = (
);

my $gnu_license = "GNU_license.txt";
my @GNU_LICENSE = loadLicense($gnu_license);
my @GNU_BODY = @GNU_LICENSE;
splice @GNU_BODY, 0, 8;

my $mit_license = "MIT_license.txt";
my @MIT_LICENSE = loadLicense($mit_license);
my @MIT_BODY = @MIT_LICENSE;
splice @MIT_BODY, 0, 6;

my $ccm_license = "CCM_license.txt";
my @CCM_LICENSE = loadLicense($ccm_license);
my @CCM_BODY = @CCM_LICENSE;
splice @CCM_BODY, 0, 1;

my @LICENSE = ();
my @LICENSE_BODY = ();

my $dir    = shift @ARGV || Usage();
my $xfile  = shift @ARGV;

if ($xfile) {
    open(IN, $xfile) || die "Failed to open '$xfile' : $!\n";
    while (my $x = <IN>) {
        chomp($x);
        $exclude{$x} = 1;
    }
    close(IN);
}

# Traverse desired filesystems
File::Find::find({wanted => \&wanted}, $dir);

for my $file (sort @files) {

    my $f = basename($file);
    next if $exclude{$f};
    my $task = get_task($file);
    print "\n\n PROCESSING '$file' --- task '$task' \n";
    next if $task == 0;
    update_license($task, $file) if $DOUPDATES;
}

exit;


sub wanted {
    /^.*\.(h|cpp|c|sql|hpp|rst)\z/s &&
    push @files, $name;
}

sub loadLicense {
    my $file_name = shift;
    my @file_storage;
    open(IN, $file_name) || die "Failed to open '$file_name' : $!\n";
    @file_storage = <IN>;
    close(IN);
    return @file_storage;
}

# When the first line is not equal it doesnt have the
# generated license.
# The generated license has to be added
# And Manually fixed.
#
# When the first line is equal, then we skip up to find
# The "-------" line in both files
# The rest of the license must be equal
#
sub get_task{
    my $f = shift;

    open(IN, $f) || return 0;

    my $line = <IN>;

    my $license_type = 0;
    $license_type = 1 if $GNU_LICENSE[0] eq $line;
    $license_type = 2 if $MIT_LICENSE[0] eq $line;
    $license_type = 3 if $CCM_LICENSE[0] eq $line;

    #The license is not found
    if ($license_type == 0) {
        close(IN);
        # task is "add a licence"
        return 1;
    }

    # look for the dividing line
    if ($license_type != 3) {
        while ($line and ($line !~ "------")) {
            $line = <IN>;
        }

        #The dividing line is not found
        if (!$line) {
            close(IN);
            # task is "add a licence"
            return 1;
        }
    }

    @LICENSE_BODY = @GNU_BODY if $license_type == 1;
    @LICENSE_BODY = @MIT_BODY if $license_type == 2;
    @LICENSE_BODY = @CCM_BODY if $license_type == 3;


    #The license is found but the body is different
    for (my $i = 0; $i < @LICENSE_BODY; $i++) {

        $line = <IN>;
        if ($LICENSE_BODY[$i] ne $line) {
            close(IN);
            # task is "update the licence"
            return 2;
        }
    }

    close(IN);
    # task is do nothing
    return 0;
}

# task = 0 Do nothing
# task = 1 Insert complete license
# task = 2 Update license body
sub update_license {
    my $task = shift;
    my $file_name = shift;

    return if $task == 0;

    # read the file
    my @file = ();
    open(IN, $file_name) || die "Failed to read '$file_name' : $!\n";
    @file = <IN>;
    close(IN);

    my $license_type = 0;
    @LICENSE = @GNU_LICENSE;
    @LICENSE_BODY = @GNU_BODY;
    if ($file[0] eq  $MIT_LICENSE[0])  {
        $license_type = 2;
        @LICENSE = @MIT_LICENSE;
        @LICENSE_BODY = @MIT_BODY;
    } elsif ($file[0] eq  $CCM_LICENSE[0])  {
        $license_type = 3;
        @LICENSE = @CCM_LICENSE;
        @LICENSE_BODY = @CCM_BODY;
    }



    if ($task == 1) {
        print "  Adding full license\n";
        print "     --> Please remove old license and update names if needed\n";
        $LICENSE[1] =~ s/__FILENAME__/$file_name/;
        @file = (@LICENSE, @file);

    } else {
        #task = 2
        print "  Changing Body of license\n";


        # Find the dividing line
        my $first = 0;
        my $last = 0;
        if ($license_type !=3) {
            while ($file[$first] !~ "------") {
                $first++;
            }
        } else {
            $first = 2;
        }

        $first++;
        $last = $first;

        # Find the last line
        #while ($file[$last] =~ne $LICENSE[$#LICENSE]) {
        while ( $file[$last] !~ /\*+PGR-/) {
            $last++;
        }

        splice @file, $first, $last-$first+1, @LICENSE_BODY;

    }
    open(OUT, ">$file_name") || die "Failed to rewrite '$file_name' : $!\n";
    print OUT @file;
    close(OUT);

}

