#!/usr/bin/perl -w

# @author: Robin Pronk

use sigtrap;
use strict;
use threads;
use threads::shared;

$SIG{INT} = $SIG{TERM}= $SIG{HUP}=\&MrPropper;

# -- config --

# be verbose to console?
my $verbose = 0;
# scrollspeed (higher is slower)
my $scroller = 3;
# change port and hostname for LCDd server
my $Client = LCDdClient->new(Port => 13666 ,Host => 'localhost');

# -- end of config --

print "connecting to LCDd ...\n\n"  if $verbose;
my $dsp_width = $Client->DispWidth();
my $dsp_hight = $Client->DispHight();

my $mocpScreen;
$mocpScreen = LCDdScreen->new(Client => $Client, ScreenName => "MOC");
$mocpScreen->AddWidget(WidgetId =>"title",WidgetType=>"title");
$mocpScreen->SetWidget(WidgetId =>"title",Parameter=>"MOC");
$mocpScreen->AddWidget(WidgetId =>"one",WidgetType=>"scroller");
$mocpScreen->AddWidget(WidgetId =>"two",WidgetType=>"scroller");
$mocpScreen->AddWidget(WidgetId =>"three",WidgetType=>"scroller");
our $LCDd_status: shared = "";
print "initialized the mocp screen ...\n"  if $verbose;

while(1) {
        while(defined(my $line = $Client->Send)){
          if ($line =~ /^success$/ ) {next;}
          if ($line=~/^huh/){die "Error: $line\n"}
          $LCDd_status = $line;
          print "$line \n" if $verbose;}

        #the mocp screen
        if ($LCDd_status=~m/^listen MOC$/) {
                my $mocp = "/usr/bin/mocp -i";
                my $mocp_test=`ps a | grep mocp | grep -v grep | wc -l`;
                my $mocp_one = "";
                my $mocp_two = "";
                my $mocp_three = "";

                if ($mocp_test > 0 || 1){
                        my $mocp_file = `$mocp | grep File | sed 's/File: //'`;
                        chomp($mocp_file);
                        # something playing?
                        if (length($mocp_file) > 1) {
                                # radio 538 hack
                                if ($mocp_file eq "http://82.201.100.9:8000/radio538") {
                                        $mocp_one = "Radio 538";
                                        $mocp_three = `$mocp | grep CurrentTime | sed 's/CurrentTime: //'`;
                                } else {
                                        $mocp_one = `$mocp | grep Artist | sed 's/Artist: //'`;
                                        $mocp_two = `$mocp | grep SongTitle | sed 's/SongTitle: //'`;
                                        my $mocp_timeplayed = `$mocp | grep CurrentTime | sed 's/CurrentTime: //'`;
                                        my $mocp_timetotal = `$mocp | grep TotalTime | sed 's/TotalTime: //'`;
                                        chomp($mocp_timeplayed, $mocp_timetotal);
                                        $mocp_three = "$mocp_timeplayed / $mocp_timetotal";
                                }
                        } else {
                               $mocp_one = "Playlist is empty.";
                        }
                        chomp($mocp_one,$mocp_two,$mocp_three);
                        $mocpScreen->SetWidget(WidgetId =>"one",Parameter=>" 1 2 $dsp_width 1 h $scroller {$mocp_one  }");
                        $mocpScreen->SetWidget(WidgetId =>"two",Parameter=>" 1 3 $dsp_width 1 h $scroller {$mocp_two  }");
                        $mocpScreen->SetWidget(WidgetId =>"three",Parameter=>" 1 4 $dsp_width 1 h $scroller {$mocp_three}");
                } else {
                        $mocpScreen->SetWidget(WidgetId =>"title",Parameter=>"{MOC isn't running}")
                }
                print "showing mocp screen\n"  if $verbose;
        }
}

sub MrPropper{$Client->Close||die "close: $!";print"\n\tgood bye ...\n\n";exit 0;}

package LCDdScreen;
        no strict "refs";
sub new(){
        my $class = shift;my $self = { };
        foreach (qw/Client ScreenName /){
        my $name  = shift;my $value = shift;
        $self->{$name}=$value;}
        bless($self,$class);
        $self->{Client}->Send("screen_add $self->{ScreenName}");
        $self->{Client}->Send("screen_set $self->{ScreenName} name {$self->{ScreenName}} heartbeat off");
        return($self);}

sub AddWidget(){
        my $self = shift;my $hash =ref(my %hash);
        foreach (qw/WidgetId WidgetType /){
        my $name  = shift;my $value = shift;
        $hash->{$name}=$value;}
        $self->{Client}->Send("widget_add $self->{ScreenName}  $hash->{WidgetId} $hash->{WidgetType}");}

sub SetWidget(){
        my $self = shift;my $hash =ref(my%hash);
        foreach (qw/WidgetId Parameter /){
        my $name  = shift;my $value = shift;
        $hash->{$name}=$value;}
        $self->{Client}->Send("widget_set $self->{ScreenName} $hash->{WidgetId} $hash->{Parameter}");}

package LCDdClient;
sub new(){
        use Fcntl;use IO::Socket;
        my $class = shift;my $self = { };
        foreach (qw/Host Port/){
        my $name  = shift;my $value = shift;
        $self->{$name}=$value;}
        my $host=$self->{Host};my $port=$self->{Port};
        my $remote = IO::Socket::INET->new(Proto=> "tcp",PeerAddr=> $host,
        PeerPort=> $port)or die "Cannot connect to LCDd daemon\n";
        $remote->autoflush(1);sleep (1);
        print $remote "hello\n";
        my $lcdresponse = <$remote>;
        my $dsp_width=$lcdresponse;
        $dsp_width =~ s/wid\s\d\d//;
        $dsp_width=$&;
        $dsp_width=~s/wid\s//;
        my $dsp_hight = $lcdresponse;
        $dsp_hight =~ s/hgt\s\d//;
        $dsp_hight=$&;
        $dsp_hight=~s/hgt\s//;
        fcntl($remote, F_SETFL, O_NONBLOCK);
        print $remote "client_set name {yaLCD}\n";
        $lcdresponse = <$remote>;
        $self->{DispHight} = $dsp_hight;
        $self->{DispWidth} = $dsp_width;
        $self->{Connection}=$remote;
        bless($self,$class);
        return($self);}

sub DispWidth(){
        my $self = shift;
        return ($self->{DispWidth});}

sub DispHight(){
        my $self = shift;
        return ($self->{DispHight});}

sub Send(){
        my $self = shift;
        my $payload = shift;
        my $remote = $self->{Connection};
        if($payload){print $remote "$payload\n";}
        my $response = <$remote>;
        return ($response);}

sub Close(){
        my $self = shift;
        close($self->{Connection});}
