#!/usr/bin/perl

#   Copyright (C) 2008 by Frank Scheffold
#
#
#   This program 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 2 of the License, or
#   (at your option) any later version.
#
#   This program 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 this program; if not, write to the
#   Free Software Foundation, Inc.,
#   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.




use strict;
use warnings;
use Getopt::Long;
use Pod::Usage;
use DBI;

#use FindBin qw($Bin);

sub checkConfig($$);
sub createPlaylist($$$$$);
sub readPlaylistNames($);
sub searchForPlaylistName($$);

my (%dboptions, $configfile, $help, $co, $m3ufile, $playlistname, $playlists) = ();

#my $defaultconfigfile = "$Bin/myth-m3uimporter.conf";
my $defaultconfigfile = "$ENV{HOME}/.myth-m3uimporter.conf";
my @entrykeys = qw (dbDriver dbSchema dbName dbHost dbPort dbUser dbPassword musicLocation mythHostname);

GetOptions(
	   "config|c=s"		=> \ $configfile,
	   "file|f=s"		=> \ $m3ufile,
	   "name|n=s"		=> \ $playlistname,
	   "help|h"			=> \ $help) || pod2usage( {-exitstatus => 1, -verbose => 2 }
);
pod2usage({ -exitstatus => 1, -verbose=>2}) if $help;

$configfile = $defaultconfigfile if((! defined($configfile)) || ($configfile eq ""));

$co = checkConfig( $configfile, \@entrykeys);

pod2usage({ -exitstatus => 1, -verbose=>2})  unless (defined($m3ufile));
pod2usage({ -exitstatus => 1, -verbose=>2})  unless (defined($playlistname));

die ("m3u file does not exist or is not readable") unless ((-e $m3ufile) && (-r $m3ufile));


#Init database connection
my $dsn  = "DBI:$co->{dbDriver}:database=$co->{dbName};host=$co->{dbHost}";
my $dbh = DBI::->connect( $dsn, $co->{dbUser}, $co->{dbPassword},
					 { 'RaiseError' => 1, 'AutoCommit' => 1 } )
                      or die "Couldn't connect to database: " . DBI->errstr;

$playlists = readPlaylistNames($dbh);
createPlaylist($dbh, $m3ufile, $playlistname, $playlists, $co->{mythHostname});


print "Import successfully finished\n";
$dbh->disconnect;


#######################################################################################
#									Functions
#####################################################################################
sub readPlaylistNames($){
	my ($dbh) =@_;
	my ($sth, $playlists, @row);
	$sth = $dbh->prepare(q(SELECT playlist_id, playlist_name FROM music_playlists))
            or die "Couldn't prepare statement: " . $dbh->errstr;
    $sth->execute() or die "Couldn't execute statement: " . $sth->errstr;
    while(@row = $sth->fetchrow_array()){
    	$playlists->{$row[0]} = $row[1];
    }
	return $playlists;
}

#####################################################################################

sub searchForPlaylistName($$){
	my ($playlists, $playlistname)= @_;
	my $playlist_id;
	foreach( keys %$playlists){
		$playlist_id = $_ if $playlists->{$_} eq $playlistname;
	}
	return $playlist_id;
}

#####################################################################################

sub createPlaylist($$$$$){
	my($dbh, $m3uFile, $playlistname, $playlists, $mythHostname ) = @_;
	my( $mp3, $mythEntry, $sth, $id, $lenght, $noentry, $playlist_id,$input)=();
	my $playlist_songs ="";
	my ($completelength, $songcount) =0;


	open( M3U_FILE, "< $m3uFile" )|| die ("Can't open  $m3uFile");
		while (<M3U_FILE>) {
			chomp;                  # no newline
    		s/#.*//;                # no comments
    		s/^\s+//;               # no leading white
    		s/\s+$//;               # no trailing white
    		next unless length;     # anything left?
			($mp3 = $_) =~ s/$co->{musicLocation}//g;
			$mp3 =~ s/^\///g;
			#print "MP3 = $mp3\n";
			$sth = $dbh->prepare(q(SELECT song_id, length FROM music_songs  WHERE filename like ?))
            	or die "Couldn't prepare statement: " . $dbh->errstr;
         	$sth->execute($mp3) or die "Couldn't execute statement: " . $sth->errstr;

        	($id, $lenght) = $sth->fetchrow_array();
        	if(defined($id) && defined($lenght)){
        		$songcount ++;
        		$completelength += $lenght;
        		$playlist_songs = $playlist_songs.$id.", ";
        	}else{
        		$noentry= $noentry."No Entry found for $_\n";
        }
	}
	$sth->finish();

	print $noentry if defined ($noentry);
	die "No mp3's in database found which are in the m3u file $m3ufile" unless defined($songcount);
	$playlist_songs =~ s/, $//g; #Remove last ", "...
    $playlist_id = searchForPlaylistName($playlists, $playlistname);

    if(defined($playlist_id)){
    	print "Playlist with name $playlistname already exists in database\n";
    	do{
    		print "(o)verwrite, (r)ename or (c)ancel: ";
    		chomp($input = <>);
    	} until( defined($input) && ( ($input eq "o") || ($input eq "r") || ($input eq "c" )) );
    	if($input eq "o"){
    		print "Updating playlist $playlistname\n";
    		$sth = $dbh->prepare(q(update music_playlists set playlist_songs=?,  length=?, songcount=? where playlist_id = ?))
    			or die "Couldn't prepare statement: " . $dbh->errstr;
         	$sth->execute($playlist_songs, $completelength, $songcount, $playlist_id)
         		or die "Couldn't execute statement: " . $sth->errstr;
         	$sth->finish;
         	return;
    	}
    	elsif($input eq "r"){
    		do {
    			do {
    				print "Enter new name for playlist: ";
    				chomp($playlistname = <>);
    			} until (! $playlistname eq "");
    			$playlist_id = searchForPlaylistName($playlists, $playlistname);
    			print "Playlist $playlistname already exists in database!\n" if (defined($playlist_id));
    		} while  (defined($playlist_id));
    	}
    	elsif ($input eq "c"){
    		exit(0);
    	}
    }
   	print "Insert songs from $m3uFile into the playlist $playlistname\n";
   	$sth = $dbh->prepare(q(insert into music_playlists(playlist_name,  playlist_songs,  length, songcount, hostname)
   						 values (?, ?, ?, ?,  ?))) or die "Couldn't prepare statement: " . $dbh->errstr;
	$sth->execute($playlistname, $playlist_songs, $completelength, $songcount, $mythHostname) or die "Couldn't execute statement: " . $sth->errstr;
	$sth->finish;
}

#####################################################################################

sub checkConfig($$) {
	my ($configfile, $entrykeys) = @_;
	my (%co)=();
	open( CONFIG, "< $configfile" )|| die ("Can't open  $configfile");
	while (<CONFIG>) {
		chomp;                  # no newline
    	s/#.*//;                # no comments
    	s/^\s+//;               # no leading white
    	s/\s+$//;               # no trailing white
    	next unless length;     # anything left?
		my ( $var, $value ) = split( /\s*=\s*/, $_, 2 );
		$co{$var} = $value;
	}
	close(CONFIG);

	foreach my $entry (@$entrykeys) {
		die("Config Entry <$entry> does not exist")unless exists($co{$entry});
		die("Config: $entry not set") if( (!defined($co{$entry})) ||  ($co{$entry} eq "") );
	}
	return \%co;
}


=head1 NAME
	myth-m3uimporter.pl


=head1 SYNOPSIS

	Mythtv m3u playlist importer



=head1 DESCRIPTION

  This skript imports m3u playlists in the mythtv database. You need a configuration file in your
  your home folder named "$HOME/.myth-m3uimporter.conf" which has got the following entries:

  #Perl DBI database driver
  dbDriver=mysql
  #Database schema (default in mysql)
  dbSchema=default
  #Database name
  dbName=mythtv
  #Database host
  dbHost=localhost
  #Database port
  dbPort=3306
  #Database user
  dbUser=mythtv
  Database password
  dbPassword=mythtv
  #Mythv music folder (configured in mythfrontend)
  musicLocation=/path/to/music/
  #Hostname of the mythv backend
  mythHostname=hostname


  Usage:
  myth-m3uimporter.pl -n Playlistname -f /path/to/m3u-file.m3u

Options:

  -c, --config   configfile to use. If not set the default file (set in the script) will be used.
  -f, --file     m3u file to import
  -n, --name     name of the playlist
  -h, --help     prints this short help.

=head1 AUTHOR
  Frank Scheffold (fscheffold@googlemail.com)
=cut
