#!/usr/bin/perl

use XML::DOM;
use Connect;

$debug=0;

if(length(@ARGV)==0 ) {
  die("No file specified.\n");
}

$dbh = database_open();

my $file=$ARGV[0];
my $parser=new XML::DOM::Parser;

my $doc= $parser->parsefile($file);

my @fields=('notes',        [ 'txt' ],
            'check',        [ 'type', 'condition', 'path', 'value' ],
            'download',     [ 'lang','url','saveto' ],
            'prepare',      [ 'cmd', 'timeout' ],
            'install',      [ 'cmd', 'timeout' ],
            'upgrade',      [ 'cmd', 'timeout' ],
            'remove',       [ 'cmd', 'timeout' ],
            'depends',      [ 'package-id' ],
            'supercedes',   [ 'package-id' ],
            'conflicts',    [ 'package-id' ],
            );
## $package_sth->execute('name','version','idtxt','reboot','priority','exeonce');
$package_sql="insert into packages values ( NULL, ?, ?, 0, ?, ?, ?, ?, 'From XML Import')";
$package_sth=$dbh->prepare($package_sql);

## $notes_sth->execute('pack_id','txt');
$notes_sql="update packages set notes=? where id=?";
$notes_sth=$dbh->prepare($notes_sql);

## $check_sth_level->execute( 'pack_id', 'chklevel', 'prnlevel', 'logic_text' );
$check_sql_level="insert into pack_checks select NULL, ?, ?, ?, id, NULL, NULL, NULL, NULL from pack_chklogic where value=?";
$check_sth_level=$dbh->prepare($check_sql_level);

## $check_sth_check->execute( 'pack_id', 'chklevel', 'path', 'value', 'chktype_text', 'condition_text' );
$check_sql_check="insert into pack_checks select NULL, ?, ?, NULL, NULL, pack_chktype.id, pack_chkconditions.id, ?, ? from pack_chktype,pack_chkconditions where pack_chktype.value=? and pack_chktype.id=pack_chkconditions.chktype and pack_chkconditions.value=?";
$check_sth_check=$dbh->prepare($check_sql_check);

## $download_sth->execute('pack_id','url','saveto','lang');
$download_sql="insert into pack_downloads select id, ?, ?, ? from languages where value=?";
$download_sth=$dbh->prepare($download_sql);

## $command_sth_nextPri->execute('pack_id','cmdtype_text');
$command_sql_nextPri="select ifnull(max(priority),0)+1 from pack_cmds,pack_cmdtype where pack_id=?
                      and pack_cmds.cmdtype_id=pack_cmdtype.id and pack_cmdtype.value=?";
$command_sth_nextPri=$dbh->prepare($command_sql_nextPri);

## $command_sth->execute('pack_id','priority','cmd','timeout || NULL','cmdtype_text');
$command_sql="insert into pack_cmds select NULL, ?, id, ?, ?, ? from pack_cmdtype where value=?";
$command_sth=$dbh->prepare($command_sql);

## $exits_sth->execute('cmd_id', 'exitcode', 'Normal Exit || Reboot Required');
$exits_sql="insert into pack_cmdexits select ?, ?, id from pack_cmdexitactions where value=?";
$exits_sth=$dbh->prepare($exits_sql);

## $extras_sth->execute('pack_id', 'exttype_text', 'idtxt');
$extras_sql="insert into pack_extras select NULL, ?, pack_exttype.id, packages.id from pack_exttype,packages where pack_exttype.value=? and packages.idtxt=?";
$extras_sth=$dbh->prepare($extras_sql);

foreach my $package ( $doc->getElementsByTagName("package") ) {
  $chklevel=-1;
  $nextlevel=0;

  print "Package: ";
  @sql=();
  foreach my $attribute ( 'name','revision','id','reboot','priority','execute' ) {
    $got_it=0;
    foreach my $value ( $package->getAttributeNode($attribute) ) {
      if($value) {
        if($attribute eq 'reboot') {
          if($value->getValue eq 'true') {
            push @sql,'1';
          } else {
            push @sql, '0';
          }
        } elsif($attribute eq 'execute') {
          if($value->getValue eq 'once') {
            push @sql,'1';
          } else {
            push @sql,'0';
          }
        } else {
          push @sql,$value->getValue;
        }
        if($attribute eq 'id') {
          print "  $attribute: " . $value->getValue . "\n";
        }
        $got_it=1;
      }
    }
    if (!$got_it) {
      if($attribute eq 'execute' || $attribute eq 'reboot') {
        push @sql,'0';
      } else {
        push @sql,'';
      }
    }
  }
  our $pack_id=add_package(@sql);
  @sql=();
  $field_len=@fields;
  for ($i=0;$i<$field_len;$i+=2) {
    my $field=$fields[$i];
    my $attributes=$fields[$i+1];
    $attrib_data='';
    foreach my $branch ( $package->getElementsByTagName($field)) {
      if($note_proc && ( $field ne 'notes') ) {
        $success=add_notes($pack_id,join(" - ",@sql));
        @sql=();
        $note_proc=0;
      }
      foreach my $attribute ( @$attributes ) {
        if($value=$branch->getAttributeNode($attribute)) {
          push @sql, $value->getValue;
          $attrib_data.="    $attribute: " . $value->getValue . "\n";
        } else {
          push @sql, '';
        }
      }

      if( ($field eq 'prepare' || $field eq 'install' || $field eq 'upgrade' || $field eq 'remove') && $branch ) {
        $cmd_id=add_command($pack_id,$field,@sql);
        $exit_data='';
        @sql=();
        foreach my $exitcode ( $branch->getElementsByTagName('exit') ) {
          if ( $exitcode ) {
            push @sql,$exitcode->getAttributeNode('code')->getValue;
            $exit_data.="      " . $exitcode->getAttributeNode('code')->getValue;
            if ( $exitcode->getAttributeNode('reboot') ) {
              push @sql,'Reboot Required';
              $exit_data.=": reboot";
            } else {
              push @sql,'Normal Exit';
            }
            $success=add_exit($cmd_id,@sql);
            @sql=();
            $exit_data.="\n";
          }
        }
        if($exit_data ne '') {
          $attrib_data.="    exit:\n";
          $attrib_data.=$exit_data;
          $exit_data='';
        }
      } elsif ( ( $field eq 'depends' || $field eq 'supercedes' || $field eq 'conficts' ) && $branch ){
        $success=add_extra($pack_id, $field, @sql);
        @sql=();
      } elsif ( $field eq 'notes' && $branch ) {
        $note_proc=1;
      }elsif ( $branch ) {
        $call_cmd="add_" . $field . "(" . $pack_id . ', @sql)';
        eval($call_cmd);
        @sql=();
      }
    }
  }
}

sub print_junk {
  my @data=@_;
  my $count=0;
  print "Count: " . @data . " ::: ";
  foreach my $junk ( @data ) {
    if($count) {
      print ",";
    } else {
      $count=1;
    }
    print $junk eq '' ? "NULL" : $junk;
  }
  print "\n";
}

sub add_package {
  my @data=@_;
  if(!$debug) {
    $package_sth->execute(@data) || die(join(',',@data));
    my $pack_id=$dbh->{mysql_insertid};
    return $pack_id;
  } else {
    print "add_package():\n";
    print_junk(@data);
    return 1;
  }
}

sub add_notes {
  my @data=@_;
  if (!$debug) {
    $notes_sth->execute($data[1],$data[0]);
  } else {
    print "add_notes():\n";
    print_junk(@data);
  }
  return 1;
}

sub add_check {
  my @data=@_;
  ## @data position:               0                                     2
  ## $check_sth_level->execute( 'pack_id', 'chklevel', 'prnlevel', 'logic_text' );

  ## @data position:               0                        1               1                 2            3        4
  ## $check_sth_check->execute( 'pack_id', 'chklevel', 'chktype_text', 'chktype_text', 'condition_text', 'path', 'value' );
  if( $chklevel==-1 && $data[2] ne 'logical' ) {
    # print "SUB: add_check() :: Adding Zero Level\n";
    if(!$debug) {
      $check_sth_level->execute($data[0],0,-1,'and');
    } else {
      print "Adding 0 level\n";
    }
    $chklevel++;
    $nextlevel++;
  }
  if($data[2] eq 'logical') {
    # print "SUB: add_check()/Level\n";
    if(!$debug) {
      $check_sth_level->execute($data[0],$nextlevel,$chklevel,$data[2]) || die(join(',',$nextlevel,$chklevel,@data));
    }
    $chklevel++;
    $nextlevel++;
  } else {
    if(!$debug) {
      $check_sth_check->execute($data[0], $chklevel, $data[3], $data[4], $data[1], $data[2]) || die(join(',',$chklevel,@data));
    } else {
      print "add_check():\n";
      print_junk($chklevel,@data);
    }
  }

  return 1;
}

sub add_download {
  my @data=@_;
  ## @data position:           1      0        2       3
  ## $download_sth->execute('lang','pack_id','url','saveto');
  # print "SUB: add_download()\n";
  if(!$debug) {
    $download_sth->execute($data[0],$data[2],$data[3],$data[1]) || die(join(',',@data));
  } else {
    print "add_download():\n";
    print_junk(@data);
  }
  return 1;
}

sub add_command {
  my @data=@_;
  # print "SUB: add_command()\n";
  ## @data_position:                   0           1
  ## $command_sth_nextPri->execute('pack_id','cmdtype_text');
  $command_sth_nextPri->execute($data[0],$data[1]) || die(join(',',@data));
  ( $nextpri ) = $command_sth_nextPri->fetchrow_array;
  ## @data position:           0             1                     2      3
  ## $command_sth->execute('pack_id', 'cmdtype_text','priority','cmd','timeout || NULL');
  if (!$debug) {
    $command_sth->execute($data[0],$nextpri,$data[2], $data[3] eq '' ? '3600' : $data[3], $data[1] ) || die(join(',',$nextpri,@data));
    return $dbh->{mysql_insertid};
  } else {
    print "add_command():\n";
    print_junk(@data);
    return 1;
  }
}

sub add_exit {
  my @data=@_;
  # print "SUB: add_exit()\n";
  ## @data position:       0           1           2
  ## $exits_sth->execute('cmd_id', 'exitcode', 'Normal Exit || Reboot Required');
  if(!$debug) {
    $exits_sth->execute(@data) || die(join(',',@data));
  } else {
    print "add_exit():\n";
    print_junk(@data);
  }
  return 1;
}

sub add_extra {
  my @data=@_;
  # print "SUB: add_extra()\n";
  ## @data position                    0          1
  ## $extras_sth_nextPri->execute('pack_id','exttype_text');

  ## @data position:         0            1            2
  ## $extras_sth->execute('pack_id','exttype_text', 'idtxt');
  if (!$debug) {
    $extras_sth->execute($data[0],$data[1],$data[2]) || die(join(',',@data));
  } else {
    print "add_extra():\n";
    print_junk(@data);
  }

  return 1;
}
