#!/usr/bin/perl

my $debug = 0; # Set to 1 to put the script in debug mode

use POSIX;
use DBI;
use DBD::mysql;
use Config::INI::Reader;

my $confcontents = Config::INI::Reader->read_file('/etc/homeaudio.ini');
my $Config = $confcontents->{_};

$dsn = "DBI:mysql:" . $Config->{DBNAME} . ":" . $Config->{DBHOST};
$dbh = DBI->connect($dsn, $Config->{DBUSER}, $Config->{DBPASS}, {RaiseError=>1});

sub getNextSong() {
   # Set up our variables
   my $songid = 0;
   my $song = "";
   my $qid = 0;

   # If Christmas is active we should always make sure that a
   # Christmas song has played within the last frequency interval.
   $sth = $dbh->prepare("SELECT value FROM settings WHERE parameter='CHRISTMAS'");
   $sth->execute();
   @row = $sth->fetchrow_array();
   $sth->finish();
   $christmasactive = $row[0] eq "true" ? 1 : 0;
   $forcechristmas = 0;
   if ( $christmasactive ) {
      if ( $debug ) { print "Christmas is active.\n"; }
      $sth = $dbh->prepare("SELECT value FROM settings WHERE parameter='CHRISTMASFREQ'");
      $sth->execute();
      @row = $sth->fetchrow_array();
      my $christmasfreq = $row[0];
      $sth->finish();
      if ( $debug ) { print "Christmas frequency is (${christmasfreq}). Checking if Christmas song was played recently.\n"; }
      $sth = $dbh->prepare("SELECT COUNT(songid) FROM (SELECT songid FROM recently ORDER BY timeplayed DESC LIMIT ?) AS counter LEFT JOIN songs ON songid=id WHERE genre=?");
      $sth->execute($christmasfreq - 1, $Config->{CHRISTMASGENRE});
      @row = $sth->fetchrow_array();
      $sth->finish();
      if ( $row[0] == 0 ) {
         $forcechristmas = 1;
      }
   }
   if ( $forcechristmas ) {
      if ( $debug ) { print "No Christmas songs found in the last ${christmasfreq}. Forcing one to play.\n"; }
      $queueselect = "SELECT id FROM queues WHERE name='" . $Config->{CHRISTMASGENRE} . "'";
      $sth_first = $dbh->prepare("SELECT qid, songid, CONCAT(path, song) FROM queuecontents AS qc LEFT JOIN songs ON songid=id WHERE qc.timesplayed=0 AND qid=(${queueselect}) ORDER BY RAND() LIMIT 1");
      $sth_first->execute();
      $numsongs = $sth_first->rows;
      if ( $sth_first->rows == 0 ) {
         $sth = $dbh->prepare("UPDATE queuecontents SET timesplayed=0 WHERE qid=(${queueselect})");
         $sth->execute();
         $sth->finish();
         $sth_second = $dbh->prepare("SELECT qid, songid, CONCAT(path, song) FROM queuecontents AS qc LEFT JOIN songs ON songid=id WHERE qc.timesplayed=0 AND qid=(${queueselect}) ORDER BY RAND() LIMIT 1");
         $sth_second->execute();
         if ( $sth->rows == 1 ) {
            @row = $sth_second->fetchrow_array();
            $qid = $row[0];
            $songid = $row[1];
            $song = $row[2];
         }
         $sth_second->finish();
      } else {
         @row = $sth_first->fetchrow_array();
         $sth_first->finish();
         $qid = $row[0];
         $songid = $row[1];
         $song = $row[2];
      }
   }

   # Only try to pull from the instantq if we don't have a song yet
   if ( $songid == 0 ) {
      # if there is anything in the instantq, get the list of songs
      # (sorted by "id"), delete the most recent one and return
      # the full path to the song
      my $sth = $dbh->prepare("SELECT instantq.id, songid, CONCAT(path, song) AS songpath FROM instantq LEFT JOIN songs ON songid=songs.id ORDER BY id");
      $sth->execute();
      if ( $sth->rows > 0 ) {
         @result = $sth->fetchrow_array();
         $sth->finish();
         $id = $result[0];
         $songid = $result[1];
         $songpath = $result[2];
         $dbh->do("DELETE FROM instantq WHERE id=$id");
         $sth->finish();
         return ($songid, $songpath);
      }
      $sth->finish();
   }

   # Only try to grab the next song in the active queue if we don't have a song yet
   if ( $songid == 0 ) {
      # We wouldn't be here if there was anything in the instant queue
      # so let's find out the default queue and randomly select a song
      # from that queue which is in the group of lowest "timesplayed".
      # Basically, when a song in a queue is played by the autoplayer
      # its "timesplayed" is incremented. Each queue should have "timesplayed"
      # values of only two distinct numbers since each queue starts at 0 (zero),
      # gets incremented only when autoplayed, and won't get autoplayed again
      # until after all other lower number "timesplayed" have been played.
      if ( $debug ) { print "Trying to pull a song from the active queue.\n"; }
      $queueselect = "SELECT id FROM queues WHERE active='true'";
      $sth_first = $dbh->prepare("SELECT qid, songid, CONCAT(path, song) FROM queuecontents AS qc LEFT JOIN songs ON songid=id WHERE qc.timesplayed=0 AND qid=(${queueselect}) ORDER BY RAND() LIMIT 1");
      $sth_first->execute();
      $numsongs = $sth->rows;
      # if there are no songs returned then reset the played count to zero and try again
      if ( $sth_first->rows == 0 ) {
         if ( $debug ) { print "Found no songs. Resetting timesplayed and trying again.\n"; }
         $sth = $dbh->prepare("UPDATE queuecontents SET timesplayed=0 WHERE qid=(${queueselect})");
         $sth->execute();
         $sth->finish();
         $sth_second = $dbh->prepare("SELECT qid, songid, CONCAT(path, song) FROM queuecontents AS qc LEFT JOIN songs ON songid=id WHERE qc.timesplayed=0 AND qid=(${queueselect}) ORDER BY RAND() LIMIT 1");
         $sth_second->execute();
         if ( $sth_second->rows == 0 ) {
            if ( $debug ) { print "Found no songs after resetting timesplayed. Queue must be empty. Returning empty song.\n"; }
            return (0, "");
         }
         @result = $sth_second->fetchrow_array();
         $sth_second->finish();
      } else {
         @result = $sth_first->fetchrow_array();
         $sth_first->finish();
      }
      $qid = $result[0];
      $songid = $result[1];
      $song = $result[2];
   }

   # Increment the timesplayed for this song if a song was found
   $sound = `/usr/bin/amixer sget Master`;
   @mixer = split(/\n/, $sound);
   $muted = 1;
   if ( index($mixer[@mixer-1], "[on]") > 0 ) { $muted = 0; }
   if ( ($muted == 0) && ($songid > 0) ) {
      $sth = $dbh->prepare("UPDATE queuecontents SET timesplayed=1 WHERE qid=? AND songid=?");
      $sth->execute($qid, $songid);
      $sth->finish();
   }

   # return the song ID and the relative path
   return ($songid, $song);
}

while ( 1 ) {
   if ( -e "/tmp/homeaudio.stop" ) {
      sleep 10;
      next;
   }
   my ($songid, $song) = getNextSong();
   # if the song is blank, sleep for 60 seconds and try again
   # the song might be blank if the active queue is empty
   # or there is no active queue and the instantq is empty
   # or the song that was found in the DB doesn't exist on
   # the hard drive
   if ( $song eq "" ) {
      if ( $debug ) { print "Found no songs to play. Sleeping for 60 seconds.\n"; }
      sleep 60;
      next;
   }
   $songcmd = $Config->{MP3DIR} . $song;
   $songcmd =~ s/ /\\ /g;
   $songcmd =~ s/&/\\&/g;
   $songcmd =~ s/\(/\\\(/g;
   $songcmd =~ s/\)/\\\)/g;
   $songcmd =~ s/\[/\\\[/g;
   $songcmd =~ s/\]/\\\]/g;
   $songcmd =~ s/'/\\'/g;
   $songcmd =~ s/"/\\"/g;
   $songcmd =~ s/\$/\\\$/g;
   $songdb = $song;
   $songdb =~ s/'/\\'/g;
   $sth = $dbh->prepare("INSERT INTO recently (songid, timeplayed) VALUES(?, NOW())");
   $sth->execute($songid);
   $sth->finish();
   $sth = $dbh->prepare("SELECT timeplayed FROM recently ORDER BY timeplayed DESC limit 1 OFFSET 1000");
   $sth->execute();
   if ( $sth->rows == 1 ) {
      @row = $sth->fetchrow_array();
      $sth->finish();
      $sth = $dbh->prepare("DELETE FROM recently WHERE timeplayed <= ?");
      $sth->execute($row[0]);
   }
   $sth->finish();
   $songcmd = $Config->{MP3PLAYER} . " -q " . $songcmd;
   if ( $debug ) {
      print("Next: " . $songcmd . "\n"); $dbh->disconnect(); exit();
   } else {
      system($songcmd);
   }
}

# Close the DB connection
$dbh->disconnect();