#!/usr/bin/perl
#dermixd-control: control DerMixD

#Copyright (c) 2005-2014 Thomas Orgis (thomas@orgis.org)
#This is Open Source, Distribution and Modification under the terms of the Artistic License
#see the file LICENSE in the ThOrMA package root or at a place some steps upwards directory-wise if you got this file in a separate package

use strict;

use FindBin qw($Bin);
use lib $Bin.'/../lib/dermixd';

use Socket;
use Config::Param;
use Term::ReadLine;
use DerMixD::Control;

my $param = Config::Param::get
(
	{ 'init', "Simple script for sending mixplayd a command... \n Usage: $0 [options] command+arg\nThe script tries to be smart at start/seek/pause commands when no channel is given..." }
	,'verbose',0,'v','be more verbose about the server communication'
	,'silent',0,'s','do not even give a note on success'
	,'stay',0,'S','stay connected after commands have been issued and print any server messages'
	,'file',0,'f','read commands from files (scripts)'
	,'debug',0,'d','general debugging'
	,DerMixD::Control::params()
);
$param->{'dermixd-debug'} = 1 if $param->{debug};

#first I simply died on error creating connection... that is not good for Web-frontend
#Thus, returned undef on error... that was somehow not consistent with my different perl versions (5.6 vs 5.8)
#so, now checking manually if there is a connection online

my $name = 'dermixd-control';
my $pal = new DerMixD::Control($param);
unless($pal->{online}){die "Not online ($!)\n";}

local(*DAT);

if($param->{file})
{
	unless(@ARGV)
	{
		print STDERR "Reading plain script from standard input.\n";
		ScriptWork(\*STDIN);
	}
	else
	{
		foreach my $f (@ARGV)
		{
			if(open(DAT, '<'.$f))
			{
				ScriptWork(\*DAT);
				close(DAT);
			}
			else{ print STDERR $name.': error opening '.$f."\n"; }
		}
	}
}
elsif(@ARGV)
{
	DoWork(\@ARGV);
}
else
{
	if(-t STDIN)
	{
		print STDERR "Reading interactive commands from the terminal...\n";
		print STDERR "There is some basic tab-completion using a readline variant (hopefully).\nPlease be not surprised if this is confused by funky file names with spaces or even quotes in them.\n";
		TermWork();
	}
	else
	{
		print STDERR "Reading plain script from standard input.\n";
		ScriptWork(\*STDIN);
	}
}

if($param->{stay} and $pal->{online})
{
	$pal->dump_messages();
}

# What is happening here? I have to explicitly undef $pal so that the destructor can work.
# Otherwise, the socket handle is undef already?!
$pal = undef;
exit(0);

sub ScriptWork
{
	my $file = shift;
	while(<$file>)
	{
		my $line = $_;
		Work($line);
	}
}

sub TermWork
{
	my $rl = new Term::ReadLine 'dermixd';
	while(1)
	{
		my $line = $rl->readline($name.'> ');
		if($line =~ /\S/)
		{
			$line =~ s/^\s+//;
			# Really wanna strip? Might be a file name!
			#$line =~ s/\s+$//;
			unless(Work($line)){ return; }
			$rl->addhistory($line);
		}
	}
}

sub Work
{
	require Text::ParseWords;
	my $line = shift;
	if($line =~ /^\s*([^#\s].*)$/)
	{
		#DoWork wants an array like @ARGV
		#I have a string that possibly contains quotes...
		#... for quoting spaces or as part of the data, gnnn.
		my @cl = Text::ParseWords::parse_line('\s+',0,$1);

		if(@cl)
		{
			my $com = $cl[0];
			DoWork(\@cl);
		}
		else{ print "$name: error parsing line\n"; }
	}
	unless($pal->{online})
	{
		return 0; # end
	}
	else
	{
		return 1; # continue
	}
}

sub DoWork
{
	my $bla = '';
	my $goingon = 1;
	
	my $arg = shift;
	# readline likes to add an empty token then completing
	if($arg->[$#{$arg}] eq ''){ pop(@{$arg}); }

	if($arg->[0] eq 'wait')
	{
		shift(@{$arg});
		$goingon = 0;
		print "$name: error with wait meta-command\n" unless $pal->Wait($arg);
	}
	#search for files to load
	elsif($arg->[0] =~ /^(load|play)$/ and $param->{remote} eq 'localhost')
	{
		#arg->[1] is channel, arg->[2] is file
		my $last = $#{$arg};
		if(-e $arg->[$last])
		{
			unless($arg->[$last] =~ /^\//){ $arg->[$last] = $ENV{PWD}.'/'.$arg->[$last]; }
		}
		elsif(not $arg->[$last] =~ /^\S+:\/\//)
		{
			if( eval { require ThOrMA::Base; } ) #find first one in thorma archive, if present
			{
				print STDERR "Searching in ThOrMA\n";
				my $ff = ThOrMA::Base::FDSearch($arg->[$last],undef,undef,1);
				if($#{$ff} == -1)
				{
					print STDERR "No existing music file found for ".$arg->[$last]."! What to load?\n";
					$goingon = 0;
				}
				else{ $arg->[$last] = ThOrMA::Base::EnvEncode($ff->[0]); print STDERR "found $arg->[$last]\n"; }
			}
			else{ $goingon = 0; print STDERR "Cannot figure out what file you mean, sorry.\n"; }
		}
	}
	
	if($goingon)
	{
		my $e = $pal->Control($arg);
		my @updated;
		while(@{$pal->{events}})
		{
			my $ev = shift(@{$pal->{events}});
			if($ev->[0] eq 'update')
			{
				unless($updated[$ev->[1]])
				{
					print "ch$ev->[1] updated (pos: $pal->{in}[$ev->[1]]{position} status: $pal->{in}[$ev->[1]]{status})\n";
				}
				$updated[$ev->[1]] = 1;
			}
			else
			{
				print "event: $ev->[0]\n";
			}
		}
		unless($param->{silent}){print join("\n",@{$e})."\n";}
	}
}
