# Part of the StreamDVD project
package StreamDVD::Gui;

use strict;
use vars qw($VERSION @ISA @EXPORT);

require Exporter;

@ISA = qw(Exporter);
@EXPORT = qw(

);


$VERSION = '0.1';

use Tk;                                                    # needed modules
use Tk::BrowseEntry;
use Tk::LabFrame;
use Tk::Photo;
use Tk::JPEG::Lite;
use StreamDVD::Defs;
use StreamDVD::Calc;
use strict;



sub new {                                                  # create new gui object
   my $class = shift;
   my $self = bless {}, $class;
   my ($conf, $conf_ok) = @_;                                   # get config object and status, if settings could be loaded
   $self->{CONFIG} = $conf;
   $self->_init($conf_ok);
   
   return $self;
}



sub status {                                               # update status line
   my $self = shift;
   my ($text) = @_;
   if( defined $text ) {
      $self->{STATUS} = $text;
      $self->{WIN_BASE}->update();
   }
   return $self->{STATUS};
}



sub refresh {                                              # refresh gui display, needed after data updates
   my $self = shift;
   $self->{WIN_BASE}->update();
}



sub show_calc {                                            # display calculator window
   my $self = shift;
   my $Calc = new StreamDVD::Calc($self->{WIN_BASE});
}



sub show_config {                                          # display configuration window
   my $self = shift;
   $self->{CONFIG}->dialog($self->{WIN_BASE});
}



sub enable_buttonbar {                                     # enable the buttons in buttonbar
   my $self = shift;
   foreach my $key (keys %{$self->{BUTTON}}) {
      my $btn = $self->{BUTTON}{$key};
      $btn->configure(-state=>"normal");
   }
}



sub disable_buttonbar {                                    # disable the buttons in buttonbar
   my $self = shift;
   foreach my $key (keys %{$self->{BUTTON}}) {
      my $btn = $self->{BUTTON}{$key};
      $btn->configure(-state=>"disabled");
   }
}



sub show_details {                                         # display title details
   my $self = shift;
   my $selectednum = $self->{LIST}->curselection;
   my $selectedtext = $self->{LIST}->get($selectednum);
   my $t = $self->{TITLE}[$selectednum];
   my @audio_select;
   my @subtitle_select;
   my @chap_select;
   my $content = "";
   my $linenum = 9;
   my $bla;

   $self->{PROJECT}->title($selectednum);                            # set displayed title as project title

   $content .= $selectedtext . "\n\n";
   $content .= "Aspect Ratio    : " . $t->aspect() . " " . $t->resolution() . "\n";           # display source data
   $content .= "Frames per Sec. : " . $t->fps() . "\n";
   $content .= "Runtime in Sec. : " . $t->length() . "\n";
   $content .= "Num. of Chapters: " . $t->chapter_count()  . "\n";

   $content .= "\nAudio Tracks:\n";                                  # list of audio tracks
   for( my $i=0 ; $i<$t->audio_count() ; $i++ ) {
      my $a = $t->audio($i);
      $content .= " " . $a->langcode() . " " . $a->channel() . "ch " . $a->format() . " (" . $a->content() . ")\n";
   }

   $content .= "\nSubtitles:\n";                                     # list of subtitles
   for( my $i=0 ; $i<$t->subtitle_count() ; $i++ ) {
      my $s = $t->subtitle($i);
      $content .= "  " . $s->language() . "  (" . $s->content() . ")\n";
   }

   $self->{DATA}->configure(-state=>"normal");                            # set textbox 'writable"
   $self->{DATA}->delete('1.0', 'end');                                   # empty textbox
   $self->{DATA}->insert('end', $content);                                # insert movie data


   for( my $i=0 ; $i<$t->audio_count() ; $i++ ) {                    # create audio check buttons
      my $index = $linenum . ".0";
      my $idx = $i;
      $bla = $self->{DATA}->Checkbutton(-variable=>\$audio_select[$idx],
                                     -command=> sub{ if( $audio_select[$idx] ) {
                                                        $self->{PROJECT}->audio_select($idx); }
                                                     else {
                                                        $self->{PROJECT}->audio_unselect($idx); }
                                                   });
      $self->{DATA}->windowCreate($index, -window=>$bla);                 # place checkbtn in data window
      my $a = $t->audio($i);
      $audio_select[$i] = 1;                                              # preselect it
      $self->{PROJECT}->audio_select($i);
      $linenum++;
   }

   $linenum += 2;
   for( my $i=0 ; $i<$t->subtitle_count() ; $i++ ) {                 # create subtitle check buttons
      my $index = $linenum . ".0";
      my $idx = $i;
      $bla = $self->{DATA}->Checkbutton(-variable=>\$subtitle_select[$idx],
                                     -command=> sub{ if( $subtitle_select[$idx] ) {
                                                        $self->{PROJECT}->subtitle_select($idx); }
                                                     else {
                                                        $self->{PROJECT}->subtitle_unselect($idx); }
                                                   });
      $self->{DATA}->windowCreate($index, -window=>$bla);                 # place checkbtn in data window
      $subtitle_select[$idx] = 0;                                         # unselect by default
      $self->{PROJECT}->subtitle_unselect($idx);
      $linenum++;
   }


   $self->{DATA}->insert('end', "\nChapter:\n");                     # build preview pic list
   for( my $i=0 ; $i<$t->chapter_count() ; $i++ ) {                       # display chapter select buttons
      my $text = $i + 1;
      my $idx = $i;
      my $btn = $self->{DATA}->Checkbutton(-text=>$text, -variable=>\$chap_select[$idx],
                                           -command=> sub{ if( $chap_select[$idx] ) {
                                                              $self->{PROJECT}->chapter_select($idx); }
                                                           else {
                                                              $self->{PROJECT}->chapter_unselect($idx); }
                                                           $self->chapter_adjust(\@chap_select);
                                          });
      $chap_select[$i] = 1;
      $self->{PROJECT}->chapter_select($i);                               # preselect all chapters
      
      $self->{DATA}->windowCreate('end', -window=>$btn);
      $self->{DATA}->insert('end', "\n");
   }

   $self->{DATA}->configure(-state=>"disabled");
}



sub chapter_adjust {                                       # adjust chapter selection
   my $self = shift;                                            # chapters are autom. selected to get a
   my ($refarr) = @_;                                           # complete block, not some single chapters
   my $start;                                                   # 2,3,4,5,6 = ok    1,2,5,6 = not ok, 5,6 are deactivated autom.
   my $end;
   my $i = 0;

   while( not $refarr->[$i] ) {                                 # scan for the first selected chapter
      $i++; 
      last if($i > $#{$refarr});
   }
   $start = $i;
   while( $refarr->[$i] ) {                                     # scan until the next unselected chapter was found
      $i++; 
      last if($i > $#{$refarr});
   }
   $end = $i;

   while( $i <= $#{$refarr} ) {                                 # unselect all following chapters
      $refarr->[$i] = 0;
      $self->{PROJECT}->chapter_unselect($i) if(defined $self->{PROJECT}->chapter_selected($i));
      $i++;
   }
}



sub dvd_auto {                                             # auto process all steps
   my $self = shift;
   my $ok = 1;

   if( ($ok) && ($self->{PROJECT}->state() == STATE_READ) ) {
      $ok = $self->dvd_build(); }

   if( ($ok) && ($self->{PROJECT}->state() == STATE_BUILD) ) {
      $ok = $self->dvd_burn(); }
}



sub dvd_burn {                                             # create image or write dvd directly
   my $self = shift;
   my $p = $self->{PROJECT};
   my $titlenum = $p->title();
   my $titleidx = $titlenum;
   my $ok = 1;

   return 0 unless($self->{PROJECT}->state() == STATE_BUILD);

   $titlenum++;
   $self->disable_buttonbar();

   if( $self->{CONFIG}->burn() ) {
      $self->status("Writing DVD ... ");
      if( main::dvd_burn($titleidx, \$self->{STATUS}) ) {
         $self->status("Writing DVD ... done"); }
      else {
         $self->status("Writing DVD ... failed");
         $ok = 0;
      }
   }
   else {
      if( not main::create_dir($p->dir().DIR_ISO) ) {                        # check/create data subdir
         $self->status("ERROR: cannot create data directory");
         $self->enable_buttonbar();
         return 0;
      }

      $self->status("Creating ISO Image ... ");                              # create video dvd image
      if( main::dvd_image($titleidx, \$self->{STATUS}) ) {
         $self->status("Creating ISO Image ... done"); 
         $self->{PROJECT}->state(STATE_BURN);
      }
      else {
         $self->status("Creating ISO Image ... failed");
         $ok = 0;
      }
   }

   $self->enable_buttonbar();

   return $ok;
}



sub dvd_build {                                            # read video stream and build dvd structure
   my $self = shift;
   my $p = $self->{PROJECT};
   my $titlenum = $p->title();
   my $titleidx = $titlenum;
   my $ok = 1;

   return 0 unless($self->{PROJECT}->state() == STATE_READ);

   $titlenum++;
   $self->disable_buttonbar();

   $self->status("Analyzing Selection ... ");

   if( not main::dvd_analyze($titleidx, \$self->{STATUS}) ) {
      $self->status("Analyzing Selection ... failed");
      $ok = 0;
   }
   else {
      $self->status("Analyzing Selection ... done, using factor " . $p->factor() ); }

   if( $ok && (not main::create_dir($p->dir().DIR_DVD)) ) {          # check/create data dir
      $self->status("ERROR: cannot create data directory");
      $ok = 0;
   }

   $self->status("Recoding Movie ... ") if( $ok );

   if( $ok && (not main::dvd_build($titleidx, \$self->{STATUS})) ) {
      $self->status("Recoding Movie ... failed"); 
      $ok = 0;
   }
   else {
      $self->status("Recoding Movie ... done"); 
      $self->{PROJECT}->state(STATE_BUILD);
   }

   $self->enable_buttonbar();

   return $ok;
}



sub dvd_probe {                                            # read dvd title
   my $self = shift;
   my $maintitle;

   $self->disable_buttonbar();
   $self->status("reading dvd info ... ");
   $maintitle = main::dvd_probe(\$self->{STATUS});

   if( $maintitle == -1 ) {
      $self->status("reading dvd info ... failed"); }
   else {
      $self->status("reading dvd info ... done"); 
      $self->{PROJECT}->title($maintitle);

      for( my $i=0 ; $i<=$#{$self->{TITLE}} ; $i++ ) {
         $self->{LIST}->insert('end', "Title " . ($i+1)); }
      $self->{LIST}->selectionSet($maintitle,$maintitle);                 # auto select main titleset

      $self->{PROJECT}->state(STATE_READ);
      $self->show_details();
   }
   $self->enable_buttonbar();
}



sub new_project {                                          # create new project
   my $self = shift;
   my ($name, $dir) = @_;
   $self->{PROJECT} = main::new_project($name, $dir);
   $self->{TITLE} = main::new_titlelist();
   $self->{PROJECT}->state(STATE_NEW);
}



sub Exit {                                                 # leave program
   my $self = shift;
   my $Wmain = $self->{WIN_BASE};
   $Wmain->destroy;
}



sub _init {                                                # process startup stuff
   my $self = shift;
   my ($conf_ok) = @_;
   
   $self->_init_basewindow();
   $self->_init_new_project_dlg();
   $self->show_config() unless $conf_ok;
}



sub _init_basewindow {
   my $self = shift;
   my ($name) = @_;
   my $Wmain = new MainWindow;
   $Wmain->title(PROG_NAME . " v" . PROG_VERSION);

   my $FRMbutton = $Wmain->Frame(-borderwidth=>2)->pack(-side=>"top", -fill=>"x");
   $self->{BUTTON}{EXIT} = $FRMbutton->Button(-text=>"Close",-command=>sub{ $Wmain->destroy;} )->pack(-side=>"left");
   $self->{BUTTON}{READ} = $FRMbutton->Button(-text=>"Read DVD",-command=>sub{ $self->dvd_probe;} )->pack(-side=>"left");
   $self->{BUTTON}{RECODE} = $FRMbutton->Button(-text=>"Build DVD",-command=>sub{ $self->dvd_build;} )->pack(-side=>"left");
   $self->{BUTTON}{BURN} = $FRMbutton->Button(-text=>"Write DVD",-command=>sub{ $self->dvd_auto;} )->pack(-side=>"left");
   $self->{BUTTON}{SETTING} = $FRMbutton->Button(-text=>"Settings", -command=>sub{ $self->show_config();} )->pack(-side=>"right");
   $self->{BUTTON}{CALC} = $FRMbutton->Button(-text=>"Calc",-command=>sub{ $self->show_calc;} )->pack(-side=>"right");

   my $FRMdata = $Wmain->Frame(-borderwidth=>2)->pack(-side=>"top", -expand=>1, -fill=>"both");
   my $Titlelist = $FRMdata->Scrolled("Listbox", -scrollbars=>"se", -selectmode=>"single", -width=>25)->pack(-side=>"left", -fill=>"y", -expand=>1);
   $Titlelist->eventAdd('<<DBLClick>>'=>'<Double-Button-1>');
   $Titlelist->bind('Tk::Listbox', '<<DBLClick>>' => sub{ $self->show_details;} );
   $Titlelist->bind('<4>' => sub { $Titlelist->yview('scroll', -3, 'units') unless $Tk::strictMotif; });
   $Titlelist->bind('<5>' => sub { $Titlelist->yview('scroll', +3, 'units') unless $Tk::strictMotif; });
   $self->{LIST} = $Titlelist;

   my $Titledata = $FRMdata->Scrolled("Text", -scrollbars=>"se", -wrap=>"none", -state=>"disabled", -width=>60, -height=>25)->pack(-side=>"left", -fill=>"both", -expand =>1);
   $Titledata->bind('<4>' => sub { $Titledata->yview('scroll', -2, 'units') unless $Tk::strictMotif; });
   $Titledata->bind('<5>' => sub { $Titledata->yview('scroll', +2, 'units') unless $Tk::strictMotif; });
   $self->{DATA} = $Titledata;

   my $FRMstatus = $Wmain->Frame(-borderwidth=>2)->pack(-side=>"bottom", -expand=>1, -fill=>"x");
   $FRMstatus->Entry(-textvariable => \$self->{STATUS}, -state=>"disabled")->pack(-side=>"left", -expand=>1, -fill=>"x");

   $self->{WIN_BASE} = $Wmain;
}



sub _init_new_project_dlg {                                      # dialog, create new project
   my $self = shift;
   my $name = PROJECT_NAME;
   my $path = $self->{CONFIG}->data_dir();
   my $ok = 0;

   $self->disable_buttonbar();
   my $w = $self->{WIN_BASE}->Toplevel(-title=>"New Project");
   my $frm1 = $w->Frame(-borderwidth=>5)->pack(-side=>"top", -fill=>"x");
   $frm1->Label(-text=>"Project Name: ")->pack(-side=>"left");
   $frm1->Entry(-textvariable => \$name, -width=>20)->pack(-side=>"left", -fill=>"x");
   my $frm2 = $w->Frame(-borderwidth=>5)->pack(-side=>"top", -fill=>"x");
   $frm2->Label(-text=>"Save Dir.")->pack(-side=>"left");
   $frm2->Entry(-textvariable => \$path, -width=>30)->pack(-side=>"left", -fill=>"x");
   my $frm3 = $w->Frame(-borderwidth=>5)->pack(-side=>"top", -fill=>"x");
   $frm3->Button(-text=>"OK", -command=> sub{ $ok=1; $w->destroy; } )->pack(-side=>"left");
   $frm3->Button(-text=>"Cancel", -command=> sub{ $w->destroy; } )->pack(-side=>"left");

   $self->status("New project settings");
   $w->waitWindow();

   if( $ok ) {
      $self->new_project($name, $path); 
      $self->enable_buttonbar();
   }
   else {
      $self->Exit(); }
}




1;

