#!/usr/bin/perl -w
#
#
#  rhimport
#
#  Copyright (C) 2009 Christian Pointner <equinox@helsinki.at>
#
#  This file is part of rhimport.
#
#  rhimport is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  any later version.
#
#  rhimport is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with rhimport. If not, see <http://www.gnu.org/licenses/>.
#

use strict;

use Getopt::Long;
use DBI;
use Gtk2;
use Gtk2::GladeXML;

use lib '/usr/local/share/rhimport/';
use rhimport;
my $glade_file = '/usr/local/share/rhimport/rhimport.glade';

my $DBHOST = "airplay";
my $DBUSER = "rivendell";
my $DBPW = "lldriven";
my $DB = "rivendell";
my $HELP = 0;
my $FILE = "";
my $POOL = 0;
my $KEEPCARTS = 0;
my $DROPBOX = "";
my $LISTALLOWED = 0;

GetOptions ("help!" => \$HELP,
            "file=s" => \$FILE,
            "pool!" => \$POOL,
            "keep-carts!" => \$KEEPCARTS,
            "dropbox=s" => \$DROPBOX,
            "list-allowed!" => \$LISTALLOWED,
             ) or die();

if($HELP) {
  print << "EOF";
usage: $0 --file <audio or playlist file> --pool --keep-carts --dropbox <path to dropbox> --list-allowed

When called with no file and/or no dropbox the GUI gets started to select the missing parameters

options:
     -f | --file          the media file or playlist to import
     -p | --pool          pool mode, import media files referneced by playlist
     -k | --keep-carts    in pool mode keep existing carts instead of clearing them before import
     -d | --dropbox       the path to the dropbox to use
     -l | --list-allowed  list allowed dropboxes and exit

EOF
  exit 0;
}

my $user = `/usr/bin/id -un`;
$user =~ s/\n//;

my $dbh = DBI->connect("DBI:mysql:$DB:$DBHOST","$DBUSER","$DBPW") or die "Database Error: $DBI::errstr";
my @allowed_dbs = rhimport::get_dropboxes($dbh, $user);

if($LISTALLOWED) {
  for my $href ( @allowed_dbs ) {
    print "$href->{'NAME'} \t-> $href->{'PATH'}\n";
  }
  $dbh->disconnect();
  exit 0;
}

###########################################
## GUI mode

my $guixml;

sub set_mode_playlist_gui()
{
  if(!$guixml) {
    print STDERR "no GUI definition found!\n";
    exit 2;
  }
  
  $POOL = 1;
  my $l_mode = $guixml->get_widget('l_mode');
  $l_mode->set_label("<b>Musik Pool</b>");
  my $cb_clear_carts = $guixml->get_widget('cb_clear_carts');
  $cb_clear_carts->set_sensitive(1);
  my $l_file_playlist = $guixml->get_widget('l_file_playlist');
  $l_file_playlist->set_label("<b>Playlist</b>");
  my $filter = Gtk2::FileFilter->new;
  $filter->add_pattern("*.m3u");
  my $filechooser = $guixml->get_widget('filechooser');
  $filechooser->set_filter($filter);
}

sub set_mode_file_gui()
{
  if(!$guixml) {
    print STDERR "no GUI definition found!\n";
    exit 2;
  }
  
  $POOL = 0;
  my $l_mode = $guixml->get_widget('l_mode');
  $l_mode->set_label("<b>Sendung</b>");
  my $cb_clear_carts = $guixml->get_widget('cb_clear_carts');
  $cb_clear_carts->set_sensitive(0);
  my $l_file_playlist = $guixml->get_widget('l_file_playlist');
  $l_file_playlist->set_label("<b>Datei</b>");
  my $filter = Gtk2::FileFilter->new;
  $filter->add_pattern("*.wav");
  $filter->add_pattern("*.WAV");
  $filter->add_pattern("*.ogg");
  $filter->add_pattern("*.OGG");
  $filter->add_pattern("*.flac");
  $filter->add_pattern("*.FLAC");
  $filter->add_pattern("*.fla");
  $filter->add_pattern("*.FLA");
  $filter->add_pattern("*.mp*");
  $filter->add_pattern("*.MP*");
  my $filechooser = $guixml->get_widget('filechooser');
  $filechooser->set_filter($filter);
}

sub set_mode_disabled_gui()
{
  if(!$guixml) {
    print STDERR "no GUI definition found!\n";
    exit 2;
  }

  my @widgets = ('b_mode', 'cb_clear_carts', 'b_showcarts', 'b_apply', 'filechooser');
  for my $w ( @widgets ) {
    my $widget = $guixml->get_widget($w);
    $widget->set_sensitive(0) if($widget);
  }
}

sub toggle_mode_gui()
{
  if(!$guixml) {
    print STDERR "no GUI definition found!\n";
    exit 2;
  }

  my $co_dropbox = $guixml->get_widget('co_dropbox');
  my $to_cart = $allowed_dbs[$co_dropbox->get_active]->{'TO_CART'} if($allowed_dbs[$co_dropbox->get_active]);

  my $response = 'no';
  if(($to_cart == 0 && $POOL) ||
     ($to_cart != 0 && !$POOL)) {
    my $question = "Diese Sendung hat ";
    if($to_cart != 0) {
      $question .= "nur ein Cart";
    } else {
      $question .= "mehrere Carts";
    }
    $question .= ". Soll der Modus trotzdem gewechselt werden?";
    
    my $parent_window = $guixml->get_widget('appwin');
    my $dialog = Gtk2::MessageDialog->new ($parent_window, 'destroy-with-parent',
                                           'question', 'yes-no', $question);
    $dialog->set_default_response ('no');
    $response = $dialog->run;
    $dialog->destroy;
  }
  else {
    $response = 'yes';
  }

  if($response eq 'yes') {
    if($POOL) {
      set_mode_file_gui();
    } else {
      set_mode_playlist_gui();
    }
  }
}

my $gui_progress_cb = sub {
  my ($elapsed, $max, $text) = @_;

  if(!$guixml) {
    print STDERR "no GUI definition found!\n";
    exit 2;
  }
  my $progressbar = $guixml->get_widget('progressbar');
  $progressbar->set_text("($elapsed/$max) $text");
  $progressbar->set_fraction($elapsed/$max);
  while (Gtk2->events_pending) {
    Gtk2->main_iteration;
  }
  Gtk2::Gdk->flush;
};

my $gui_error_cb = sub {
  my ($text) = @_;

  if(!$guixml) {
    print STDERR "no GUI definition found!\n";
    exit 2;
  }
  $text .= "\n\nVorgang abbrechen?";
  my $parent_window = $guixml->get_widget('appwin');
  my $dialog = Gtk2::MessageDialog->new ($parent_window, 'destroy-with-parent',
                                         'error', 'yes-no', $text);
  $dialog->set_default_response ('no');
  my $response = $dialog->run;
  $dialog->destroy;

  return 0 if($response eq 'yes');

  return 1;
};

sub start_import_gui()
{
  if(!$guixml) {
    print STDERR "no GUI definition found!\n";
    exit 2;
  }

  my $b_apply = $guixml->get_widget('b_apply');
  my $b_close = $guixml->get_widget('b_close');
  $b_apply->set_sensitive(0);
  $b_close->set_sensitive(0);

  if(!rhimport::check_key_file()) {  
    my $parent_window = $guixml->get_widget('appwin');
    my $dialog = Gtk2::MessageDialog->new ($parent_window, 'destroy-with-parent',
                                           'error', 'ok', "Es wurde kein Import Key gefunden.");
    $dialog->run;
    $dialog->destroy;
    $b_apply->set_sensitive(1);
    $b_close->set_sensitive(1);
    return 0;
  }

  my $l_status = $guixml->get_widget('l_status');

  my $filechooser = $guixml->get_widget('filechooser');
  my $file = $filechooser->get_filename;
  if(!$file || -d $file) {
    if($POOL) {
      $l_status->set_label("Keine Playlist ausgew�hlt!");
    } else {
      $l_status->set_label("Keine Audio Datei ausgew�hlt!");
    }
    $b_apply->set_sensitive(1);
    $b_close->set_sensitive(1);
    return 0;
  }
  $filechooser->unselect_all;

  my $co_dropbox = $guixml->get_widget('co_dropbox');
  my $dropbox = $allowed_dbs[$co_dropbox->get_active]->{'PATH'} if ($allowed_dbs[$co_dropbox->get_active]);
  my $group = $allowed_dbs[$co_dropbox->get_active]->{'GROUP'} if ($allowed_dbs[$co_dropbox->get_active]);
  my $to_cart = $allowed_dbs[$co_dropbox->get_active]->{'TO_CART'} if($allowed_dbs[$co_dropbox->get_active]);

  $l_status->set_label("importiere von $file");

  my $ret;
  my $log;
  if($POOL) {
    my $cb_clear_carts = $guixml->get_widget('cb_clear_carts');
    if($cb_clear_carts->get_active) {
      $log = rhimport::clear_carts($dbh, $group, $to_cart, $gui_progress_cb);
    }
    my $import_log;
    ($ret, $import_log) = rhimport::import_playlist($file, $dropbox, $user, rhimport::get_num_carts($dbh, $group) ,$gui_progress_cb, $gui_error_cb);
    $log .= $import_log;
  } else {
    $log = rhimport::clear_carts($dbh, $group, $to_cart, $gui_progress_cb);
    my $import_log;
    ($ret, $import_log) = rhimport::import_single($file, $dropbox, $user, $gui_progress_cb, $gui_error_cb);
    $log .= $import_log;
  }

  my $parent_window = $guixml->get_widget('appwin');
  my $dialog;
  if(!$ret) {
    $l_status->set_label("Fehler beim Importieren");
    $dialog = Gtk2::MessageDialog->new ($parent_window, 'destroy-with-parent',
                                        'error', 'ok', "Fehler beim Importieren.");
#    $dialog->add_button("Log anzeigen", 1);
  } else {
    $l_status->set_label("");
    $dialog = Gtk2::MessageDialog->new ($parent_window, 'destroy-with-parent',
                                        'info', 'ok', "Der Import wurde erfolgreich abgeschlossen!");
#    $dialog->add_button("Log anzeigen", 1);
  }
  my $response = $dialog->run;
  $dialog->destroy;

#   if($response == 1) {
#     $dialog = Gtk2::MessageDialog->new ($parent_window, 'destroy-with-parent',
#                                         'info', 'ok', $log);
#     $dialog->run;
#     $dialog->destroy;    
#   }

  $b_apply->set_sensitive(1);
  $b_close->set_sensitive(1);
  return $ret;
}

sub show_used_carts_gui()
{
  if(!$guixml) {
    print STDERR "no GUI definition found!\n";
    exit 2;
  }

  my $co_dropbox = $guixml->get_widget('co_dropbox');
  my $group = $allowed_dbs[$co_dropbox->get_active]->{'GROUP'} if($allowed_dbs[$co_dropbox->get_active]);


  my $l_status = $guixml->get_widget('l_status');
  my ($low_cart, $high_cart) = rhimport::get_cart_range($dbh, $group);
  if($low_cart eq $high_cart) {
    $l_status->set_label("Cart: $low_cart");
  } else {
    $l_status->set_label("Carts: $low_cart - $high_cart");
  }

#  my $usedcartswin = $guixml->get_widget('usedcartswin');
#  $usedcartswin or die "can't find Widget";
#  $usedcartswin->resize(640,480);
#  $usedcartswin->show;
}

sub clear_status_gui()
{
  if(!$guixml) {
    print STDERR "no GUI definition found!\n";
    exit 2;
  }

  my $l_status = $guixml->get_widget('l_status');
  $l_status->set_label("");
  
  my $progressbar = $guixml->get_widget('progressbar');
  $progressbar->set_text("");
  $progressbar->set_fraction(0);
}

sub dropbox_updated_gui()
{
  if(!$guixml) {
    print STDERR "no GUI definition found!\n";
    exit 2;
  }

  my $co_dropbox = $guixml->get_widget('co_dropbox');
  if($allowed_dbs[$co_dropbox->get_active]) {
    my $to_cart = $allowed_dbs[$co_dropbox->get_active]->{'TO_CART'};
    my $group = $allowed_dbs[$co_dropbox->get_active]->{'GROUP'};
    my ($low_cart, $high_cart) = rhimport::get_cart_range($dbh, $group);
    
    if($to_cart == 0) {
      set_mode_playlist_gui();
    } else {
      set_mode_file_gui();
    }
  } else {
    set_mode_disabled_gui();
  }
}

if(!$FILE || !$DROPBOX) {
  Gtk2->init;

  $guixml = Gtk2::GladeXML->new($glade_file);
  $guixml or die "can't load glade xml file";
  require gui_callbacks;

  my $model = Gtk2::ListStore->new('Glib::String', 'Glib::String', 'Glib::String', 'Glib::String');
  for my $href ( @allowed_dbs ) {
    $model->set ($model->append, 0, $href->{'PATH'}, 1, $href->{'GROUP'}, 2, $href->{'TO_CART'}, 3, $href->{'NAME'});
  }
  my $co_dropbox = $guixml->get_widget('co_dropbox');
  $co_dropbox->set_model($model);
  my $renderer = Gtk2::CellRendererText->new;
  $co_dropbox->pack_start($renderer, 1);
  $co_dropbox->add_attribute($renderer, text => 3);
  $co_dropbox->set_active(0);
  dropbox_updated_gui();

  my $cb_clear_carts = $guixml->get_widget('cb_clear_carts');
  if($KEEPCARTS) {
    $cb_clear_carts->set_active(0);
  } else {
    $cb_clear_carts->set_active(1);
  }

  $guixml->signal_autoconnect_from_package('gui_callbacks');
  my $appwin = $guixml->get_widget('appwin');
  $appwin or die "can't find Main Window";
  $appwin->resize(800,600);
  $appwin->show;
  
  Gtk2->main;
  $dbh->disconnect();
  exit 0;
}

###########################################
## command line mode

my $cl_error_cb = sub {
  my ($text) = @_;

  print "\n$text .. cancel operation [Y/n]? ";
  my $x = scalar(<STDIN>);
  $x =~ /^n/i;
};

rhimport::check_key_file() or die "Import Key not found, use rhimport-create-id to create one\n";

(-e "$FILE") or die "file '$FILE' not found\n";
if($POOL) {
  print "will import from playlist $FILE, with user $user\n\n";
} else {
  print "will import $FILE, with user $user\n\n";
}

my $group = '';
my $to_cart = 0;
for my $href (@allowed_dbs) {
  if($href->{'PATH'} eq $DROPBOX) {
    $group = $href->{'GROUP'};
    $to_cart = $href->{'TO_CART'};
    last;
  }
}

if($group eq '') {
  print "Dropbox not found or not allowed\n";
  exit 1
}

my $ret;
my $log;
if($POOL) {
  if(!$KEEPCARTS) {
    $log = rhimport::clear_carts($dbh, $group, $to_cart);
  }

  my $import_log;
  ($ret, $import_log) = rhimport::import_playlist($FILE, $DROPBOX, $user, rhimport::get_num_carts($dbh, $group), 0, $cl_error_cb);
  $log .= $import_log;
} else {
  $log = rhimport::clear_carts($dbh, $group, $to_cart);
  my $import_log;
  ($ret, $import_log) = rhimport::import_single($FILE, $DROPBOX, $user, 0, $cl_error_cb);
  $log .= $import_log;
}

$dbh->disconnect();

if(!$ret) {
  exit 1;
}

exit 0;