#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;

use CGI qw/:standard/;
use HTML::Template;
use English qw( -no_match_vars );
use RoPkg::Simba;
use RoPkg::Exceptions;

my ($simba, $tmpl);

sub sh_index {
  $tmpl = new HTML::Template(filename => '/etc/simba/templates/cgi/start-page.tmpl',
                             loop_context_vars => 1,
                             die_on_bad_params => 0);

  $tmpl->param(MirrorsNo  => $simba->MirrorsNo);
  $tmpl->param(CommandsNo => $simba->CommandsNo);
  $tmpl->param(ExcludesNo => $simba->ExcludeNo);
  $tmpl->param(MirrorsActive => $simba->MirrorsNo({Active => 1}));
  $tmpl->param(MirrorsInProgress => $simba->MirrorsNo({InProgress => 1}));

  print header, $tmpl->output,$/;
}

sub sh_excludes_page {
  $tmpl = new HTML::Template(filename => '/etc/simba/templates/cgi/ex-index.tmpl',
                             loop_context_vars => 1,
                             die_on_bad_params => 0);

  $tmpl->param(ExcludesNo => $simba->ExcludeNo);
  if ( $simba->ExcludeNo <= 0 ) {
    print header, $tmpl->output, $/;
    return;
  }

  {
    my @exs;
    my @loop_data;

    @exs = $simba->Excludes();

    foreach(@exs) {
      my $ex = $_;
      my %e_data;

      $e_data{id}        = $ex->id;
      $e_data{MirrorID}  = $ex->MirrorID;
      $e_data{CommandID} = $ex->CommandID;
      $e_data{ExList}    = $ex->ExList;

      push(@loop_data, \%e_data);
    }

    $tmpl->param(Excludes => \@loop_data);
  }

  print header, $tmpl->output,$/;
}

sub sh_commands_page {
  $tmpl = new HTML::Template(filename => '/etc/simba/templates/cgi/cmd-index.tmpl',
                             loop_context_vars => 1,
                             die_on_bad_params => 0);

  $tmpl->param(CommandsNo => $simba->CommandsNo);
  if ( $simba->CommandsNo <= 0 ) {
    print header, $tmpl->output, $/;
    return;
  }

  {
    my @cmds;
    my @loop_data;

    @cmds = $simba->Commands();

    foreach(@cmds) {
      my $cmd = $_;
      my %c_data;

      $c_data{id} = $cmd->id;
      $c_data{Path} = $cmd->Path;
      $c_data{Args} = $cmd->Args;

      push(@loop_data, \%c_data);
    }

    $tmpl->param(Commands => \@loop_data);
  }

  print header, $tmpl->output,$/;
}

sub sh_mirrors_page {
  $tmpl = new HTML::Template(filename => '/etc/simba/templates/cgi/mirrors-page.tmpl',
                             loop_context_vars => 1,
                             die_on_bad_params => 0);

  $tmpl->param(MirrorsNo  => $simba->MirrorsNo);
  $tmpl->param(CommandsNo => $simba->CommandsNo);
  $tmpl->param(ExcludesNo => $simba->ExcludeNo);
  $tmpl->param(MirrorsActive => $simba->MirrorsNo({Active => 1}));
  $tmpl->param(MirrorsInProgress => $simba->MirrorsNo({InProgress => 1}));

  if ( $simba->MirrorsNo <= 0 ) {
    print header, $tmpl->output, $/;
    return;
  }

  {
    my @mirrors;
    my @loop_data;

    eval {
      @mirrors = $simba->Mirrors(undef, [qw(Name)]);
    };
    if (Exception::Class->caught('DB::NoResults')) {
      @mirrors = ();
    }

    foreach(@mirrors) {
      my $mirror = $_;
      my %m_data;

      foreach($mirror->GetMethods) {
        next if ( $_ eq 'StdOut' );
        next if ( $_ eq 'StdErr' );

        $m_data{$_} = $mirror->$_;
      }
      push(@loop_data, \%m_data);
    }

    $tmpl->param(Mirrors => \@loop_data);
  }

  print header, $tmpl->output,$/;
}

sub modify_ex {
  my $exid = shift;
  my $ex;
  
  $tmpl = new HTML::Template(filename => '/etc/simba/templates/cgi/ex-modify.tmpl',
                             loop_context_vars => 1,
                             die_on_bad_params => 0);

  ($ex) = $simba->Excludes({ id => $exid });

  $tmpl->param(id => $ex->id);
  $tmpl->param(MirrorID => $ex->MirrorID);
  $tmpl->param(CommandID => $ex->CommandID);
  $tmpl->param(ExList    => $ex->ExList);

  print header, $tmpl->output, $/;
}

sub modify_cmd {
  my $cmdid = shift;
  my $cmd;
  
  $tmpl = new HTML::Template(filename => '/etc/simba/templates/cgi/cmd-modify.tmpl',
                             loop_context_vars => 1,
                             die_on_bad_params => 0);

  ($cmd) = $simba->Commands({ id => $cmdid });

  $tmpl->param(id => $cmd->id);
  $tmpl->param(Path => $cmd->Path);
  $tmpl->param(Args => $cmd->Args);

  print header, $tmpl->output, $/;
}

sub modify_mirror {
  my $mirrorid = shift;
  my $mirror;
  
  $tmpl = new HTML::Template(filename => '/etc/simba/templates/cgi/mirror-modify.tmpl',
                             loop_context_vars => 1,
                             die_on_bad_params => 0);

  $mirror = new RoPkg::Simba::Mirror(
                  dbo_method => $simba->dbo_method,
                  dbo        => $simba->dbo,
                  id         => $mirrorid
                );
  eval {
    $mirror->Load();
  };
  if ( Exception::Class->caught('DB::NoResults') ) {
    print header, '<h1>Sorry. No such mirror in database</h1>',$/;
    return;
  }

  foreach($mirror->GetMethods) {
    $tmpl->param($_ => $mirror->$_);
  }

  print header, $tmpl->output, $/;
}

sub update_exclude {
  my $ex;

  ($ex) = $simba->Excludes({id => param('e_id')});

  $ex->MirrorID(param('e_MirrorID'));
  $ex->CommandID(param('e_CommandID'));
  $ex->ExList(param('e_ExList'));
  $ex->Update();
}

sub update_command {
  my $cmd;

  ($cmd) = $simba->Commands({id => param('c_id')});
  $cmd->Path(param('c_Path'));
  $cmd->Args(param('c_Args'));
  $cmd->Update();
}

sub update_mirror {
  my $mirror;

  $mirror = new RoPkg::Simba::Mirror(
                  dbo_method => $simba->dbo_method,
                  dbo        => $simba->dbo,
                  id         => param('m_id')
                );
  eval {
    $mirror->Load();
  };
  if ( Exception::Class->caught('DB::NoResults') ) {
    print header, '<h1>Sorry. No such mirror in database</h1>',$/;
    return;
  }
  
  foreach($mirror->GetMethods) {
    $mirror->$_( param('m_' . $_)) if (param('m_' . $_));
  }

  if ( $mirror->InProgress !~ m/^(0|1)$/ ) {
    if ( $mirror->InProgress =~ m/^yes$/i ) {
      $mirror->InProgress(1);
    } else {
      $mirror->InProgress(0);
    }
  }
  
  if ( $mirror->Active !~ m/^(0|1)$/ ) {
    if ( $mirror->Active =~ m/^yes$/i ) {
      $mirror->Active(1);
    } else {
      $mirror->Active(0);
    }
  }

  $mirror->Update();
}

sub display_add_exclude {
  $tmpl = new HTML::Template(filename => '/etc/simba/templates/cgi/ex-new.tmpl',
                             loop_context_vars => 1,
                             die_on_bad_params => 0);

  print header, $tmpl->output,$/;
}

sub display_add_command {
  $tmpl = new HTML::Template(filename => '/etc/simba/templates/cgi/cmd-new.tmpl',
                             loop_context_vars => 1,
                             die_on_bad_params => 0);

  print header, $tmpl->output,$/;
}

sub display_add_mirror {
  $tmpl = new HTML::Template(filename => '/etc/simba/templates/cgi/mirror-new.tmpl',
                             loop_context_vars => 1,
                             die_on_bad_params => 0);

  $tmpl->param(Active => 'yes', SyncMethod => 'rsync', Contact => '-');
  print header, $tmpl->output,$/;
}

sub add_new_exclude {
  my $ex;
  
  $ex = new RoPkg::Simba::Exclude(dbo => $simba->dbo, dbo_method => $simba->dbo_method);
 
  $ex->CommandID(param('e_CommandID'));
  $ex->MirrorID(param('e_MirrorID'));
  $ex->ExList(param('e_ExList'));
  $ex->Add();
}

sub add_new_command {
  my $cmd;
  
  $cmd = new RoPkg::Simba::Command(dbo => $simba->dbo, dbo_method => $simba->dbo_method);
 
  $cmd->Args(param('c_Args'));
  $cmd->Path(param('c_Path'));
  $cmd->Add();
}

sub add_new_mirror {
  my $mirror;

  $mirror = new RoPkg::Simba::Mirror(dbo => $simba->dbo, dbo_method => $simba->dbo_method);
  
  foreach($mirror->GetMethods) {
    $mirror->$_( param('m_' . $_)) if (param('m_' . $_));
  }

  if ( $mirror->InProgress !~ m/^(0|1)$/ ) {
    if ( $mirror->InProgress =~ m/^yes$/i ) {
      $mirror->InProgress(1);
    } else {
      $mirror->InProgress(0);
    }
  }
  
  if ( $mirror->Active !~ m/^(0|1)$/ ) {
    if ( $mirror->Active =~ m/^yes$/i ) {
      $mirror->Active(1);
    } else {
      $mirror->Active(0);
    }
  }

  $mirror->Add();
}

sub delete_exclude {
  my $ex;

  eval {
    ($ex) = $simba->Excludes({id => param('id')});
    $ex->Delete();
  };

  if ( Exception::Class->caught('DB::NoResults') ) {
    return;
  }
  return;
}

sub delete_command {
  my $cmd;

  eval {
    ($cmd) = $simba->Commands({id => param('id')});
    $cmd->Delete();
  };

  if ( Exception::Class->caught('DB::NoResults') ) {
    return;
  }
  return;
}

sub delete_mirror {
  my ($mirror, $exclude);

  $mirror = new RoPkg::Simba::Mirror(
                  dbo        => $simba->dbo,
                  dbo_method => $simba->dbo_method,
                  id         => param('id')
                );
  eval {
    $mirror->Load();
  };
  if (Exception::Class->caught('DB::NoResults')) {
    return;
  }
  else {
    $mirror->Delete();
  }

  $exclude = new RoPkg::Simba::Exclude(
                   MirrorID   => $mirror->id,
                   CommandID  => $mirror->CommandID,
                   dbo        => $simba->dbo,
                   dbo_method => $simba->dbo_method
                 );
  eval {
    $exclude->Load();
  };
  if (Exception::Class->caught('DB::NoResults')) {
    return;
  }
}

sub main {
  eval {
    $simba = new RoPkg::Simba(cfgFile => '/etc/simba/simba.cfg');
  };

  if (ref($EVAL_ERROR)) {
    print header,'<h3>Error: ',$EVAL_ERROR->error,'</h3>',$RS;
    return;
  }

  if ( request_method =~ m/^post$/i ) {
    if (param('action')) {
      if (param('action') eq 'update_mirror') {
        update_mirror();
        print redirect('simba.cgi?display_page=mirrors');
        return;
      } elsif ( param('action') eq 'update_command' ) {
        update_command();
        print redirect('simba.cgi?display_page=commands');
        return;
      } elsif ( param('action') eq 'update_exclude' ) {
        update_exclude();
        print redirect('simba.cgi?display_page=excludes');
        return;
      } elsif ( param('action') eq 'add_new_mirror' ) {
        add_new_mirror();
        print redirect('simba.cgi?display_page=mirrors');
        return;
      } elsif ( param('action') eq 'add_new_command') {
        add_new_command();
        print redirect('simba.cgi?display_page=commands');
        return;
      } elsif ( param('action') eq 'add_new_exclude') {
        add_new_exclude();
        print redirect('simba.cgi?display_page=excludes');
        return;
      }
    }
  }

  if (param('action')) {
    if (param('action') eq 'mod_mirror') {
      if (! param('id')) {
        print header,'<h1>Error. No mirror id specified</h1>',$/;
        return;
      }
      modify_mirror(param('id'));
      return;
    } elsif ( param('action') eq 'add_new_mirror') {
      display_add_mirror();
      return;
    } elsif ( param('action') eq 'add_new_cmd') {
      display_add_command();
      return;
    } elsif ( param('action') eq 'add_new_ex') {
      display_add_exclude();
      return;
    } elsif ( param('action') eq 'drop_mirror') {
      delete_mirror();
      print redirect('simba.cgi?display_page=mirrors');
      return;
    } elsif ( param('action') eq 'mod_cmd' ) {
      modify_cmd(param('id'));
      return;
    } elsif ( param('action') eq 'mod_ex' ) {
      modify_ex(param('id'));
      return;
    } elsif ( param('action') eq 'drop_cmd') {
      delete_command();
      print redirect('simba.cgi?display_page=commands');
      return;
    } elsif ( param('action') eq 'drop_ex') {
      delete_exclude();
      print redirect('simba.cgi?display_page=excludes');
      return;
    }
  }

  if ( !param('display_page') ) {
    sh_index();
    return;
  }

  if (param('display_page') eq 'mirrors') {
    sh_mirrors_page();
  } elsif ( param('display_page') eq 'commands' ) {
    sh_commands_page();
  } elsif ( param('display_page') eq 'excludes' ) {
    sh_excludes_page();
  } else {
    sh_index();
  }
}

main();
