#!/usr/bin/perl -w

use strict;

my @cmdnames;
my @cmdlevels;
my @cmdargs;
my @cmddesc;
my @cmdfunc;
my @protos;
my @files;
my @help;
my @cmdaliases;

my @filelist = <*.c>;

my $modname;

my %cmdhash;

unless (@ARGV) {
  print "Usage: $0 <module name>\n";
  exit(0);
} else {
  $modname=$ARGV[0];
}

my $smallname;
$smallname=$modname;
$smallname=~s/\.so$//;

my $cname;
$cname=$smallname . ".c";
$smallname=~s/^chanserv_//;


for (@filelist) {
  next if (/commandlist.c/);
  next if ($_ eq $cname);
  
  my $fname = $_;
  my ($cn, $cl, $ca, $cd, $cf, $cp, $ch, $cal);
  $ch="";
  $cal="";

  open INFILE,"<$fname";
  
  while(<INFILE>) {
    chomp;
    
    if (/CMDNAME: (.*)/) {
      $cn=$1;
    }
        
    if (/CMDLEVEL: (.*)/) {
      $cl=$1;
    }
    
    if (/CMDARGS: (.*)/) {
      $ca=$1;
    }
    
    if (/CMDDESC: (.*)/) {
      $cd=$1;
    }
    
    if (/CMDFUNC: (.*)/) {
      $cf=$1;
    }
    
    if (/CMDPROTO: (.*)/) {
      $cp=$1;
    }
    
    if (/CMDHELP: (.*)/) {
      $ch.=$1."\\n";
    }

    if (/CMDALIASES: (.*)/) {
      $cal=$1;
    }
  }
  
  if (defined $cn and defined $cl and defined $ca and defined $cd and defined $cf and defined $cp) {
    # valid command found 
    $cmdhash{$cn} = scalar @cmdnames;

    push @files, $fname;
    push @cmdnames, $cn;
    push @cmdlevels, $cl;
    push @cmdargs, $ca;
    push @cmddesc, $cd;
    push @cmdfunc, $cf;
    push @protos, $cp;
    push @help, $ch;
    push @cmdaliases, $cal;
  } else {
    print "Warning: found source file $fname without complete tags, skipping...\n";
  }
}

if (@files < 1) {
  print "No commands found - are you in the right directory?\n";
  print "Exiting before I destroy something important.\n";
  exit(0);
}


open CL, ">commandlist.c";

print CL "/* Automatically generated by mkcommandlist.pl, do not edit. */\n\n";
print CL "#include \"../chanserv.h\"\n\n";

# Print prototypes
print CL "/* Prototypes */\n";
foreach (@protos) {
  print CL "$_\n";
}

print CL "void ".$smallname."_init(void);\n";
print CL "void ".$smallname."_fini(void);\n\n";

print CL "\nvoid _init() {\n";
print CL "  ".$smallname."_init();\n";

sub generate_help_text {
  my ($cn, $ch) = @_;

  my %SUBS;

  $SUBS{"COMMAND"} = $cn;
  $SUBS{"UCOMMAND"} = uc($cn);

  my %realsubs;
  while(my ($key, $value) = each(%SUBS)) {
    $key = '@'.quotemeta($key).'@';
    $value = quotemeta($value);
    $ch =~ s/$key/$value/g;
  }

  return $ch;
}

sub writecmd {
  my ($cn, $i, $isalias) = @_;

  my $cl = $cmdlevels[$i];
  if ($isalias) {
    $cl .= " | " if ($cl ne "");
    $cl .= "QCMD_ALIAS";
  }

  print CL "  chanservaddcommand(\"".$cn."\", ".($cl).", ".($cmdargs[$i]).", ";
  print CL ($cmdfunc[$i]).", \"".($cmddesc[$i])."\", \"".(generate_help_text($cn,$help[$i])),"\");\n";
}

for (my $i=0;$i<scalar @cmdnames;$i++) {
  writecmd($cmdnames[$i], $i, 0);

  foreach (split / /, $cmdaliases[$i]) {
    writecmd($_, $i, 1);
  }
}

print CL "}\n\nvoid _fini() {\n";
print CL "  ".$smallname."_fini();\n";

sub writercmd {
  my ($cn, $i) = @_;
  print CL "  chanservremovecommand(\"".$cn."\", ".($cmdfunc[$i]).");\n";
}

for (my $i=0;$i<scalar @cmdnames;$i++) {
  writercmd($cmdnames[$i], $i);

  foreach (split / /, $cmdaliases[$i]) {
    writercmd($_, $i);
  }
}

print CL "}\n";

close CL;

open MF,">.autobuild.mk";

print MF "# Automatically generated Makefile, do not edit.\n";

print MF "\n$modname: ";

push @files,"commandlist.c";

push @files,$cname;

foreach (@files) {
  s/.c$/.o/;
  print MF "$_ ";
}

print MF "\n";

close MF;
