#!/usr/bin/perl

use POSIX qw(strftime);

use RPC::XML::Server;

use lib '/opt/oma/reboot';
use REBOOTPARSE;
use REBOOT;
use lib '/opt/oma/oma-bin';
use OMA;
use lib '/opt/oma/transact';
use XSQL;
use Encode;
use XML::RSS;
use HTTP::Date;
use URI;

local %sqlattr;
local %sqlval;
local $sqlcmd;
local %count;

$db = OMA::opendb;

sub LOG {
	my $line=shift;
	my $now = strftime "%Y-%b-%e %H:%M:%S", localtime;
	open(F,">> /opt/oma/omarpcserver.log");
	print F "$now: $line\n";
	close(F);
}

sub latest_easy {
    my $node = shift;
    my $order = shift;
    my @row;
    my $st;
    my $ret;

    if(!$order) {
        $order = "item.description, reboot_page.dc__title";
    }
    $st = $db->prepare("
        SELECT reboot_page.ID, reboot_page.dc__title, reboot_page.dc__publisher
        FROM  item, reboot_conn, reboot_page
        WHERE item.node_sid = $node
        AND   item.type='reboot'
        AND   item.sid = reboot_conn.item_sid
        AND   reboot_conn.reboot_page = reboot_page.ID
        AND   reboot_conn.location = reboot_page.location
        AND   item.published > 0
        ORDER BY $order
    ");
    $st->execute();
	$ret = "<straightExchange>\n\n";
    while(@row=$st->fetchrow()) {
		$ret .= "\t<entry>\n\t\t<id>$row[0]</id>\n\t\t<publisher>$row[2]</publisher>\n\t</entry>\n\n";
    }
	$ret .= "</straigtExchange>";
    $st->finish();
    return($ret);
}



sub latest_rss {
    my $node = shift;
    my $path = shift;
    my @row, @row2;
    my $st, $st2;
    my $ret;
	my $lpath = $path;

	$lpath =~ s/\ /%20/g;

    my %hashrow;
	my $rss = new XML::RSS (version => '1.0');

	$rss->channel(
		title        => "$path \@ reboot.fm",
		link         => URI->new("http://$OMA::OMAHOST/$OMA::BASE$lpath/"),
		description  => "reboot.fm is a radio project in berlin. archive.reboot.fm is the archiving backend of this project.",
		dc => {
			date       => eval { $t=HTTP::Date::time2isoz(time); $t=~s/\ /T/; $t },
			subject    => "Free Software for Open Radios",
			creator    => 'thomax@icf.de',
			publisher  => 'thomaxicf.de',
			rights     => 'Copyright 2003, reboot.fm',
			language   => 'en-us',
		},
		syn => {
			updatePeriod     => "hourly",
			updateFrequency  => "1",
			updateBase       => "1901-01-01T00:00+00:00",
		},
		taxo => [
			'http://dmoz.org/Arts/Radio'
			#,'http://'
		]
	);

	$rss->textinput(
		title        => "quick finder",
		description  => "Use the text input below to search archive.reboot.fm",
		name         => "qstring",
		link         => "http://archive.reboot.fm/oma-bin/usearch",
	);

    $st = $db->prepare("
        SELECT	item.*, reboot_page.*
        FROM  item, reboot_conn, reboot_page
        WHERE item.node_sid = $node
        AND   item.type='reboot'
        AND   item.sid = reboot_conn.item_sid
        AND   reboot_conn.reboot_page = reboot_page.ID
        AND   reboot_conn.location = reboot_page.location
        ORDER BY reboot_page.ID DESC
    ");
#        AND   item.published > 0
    $st->execute();
	$st->bind_columns(\(@hashrow{@{$st->{NAME_lc}}}));

	my $count = 0;
    while((@row=$st->fetchrow()) && ($count < 19)) {
		$count++;
		$file="http://$OMA::OMAHOST/$OMA::BASE$lpath/$hashrow{sid}.html";
		$file=~s/\ /%20/g;
		$file=~s/\?/%3f/g;

        $st2 = $db->prepare("
                                SELECT  dc__creator, dc__creator__role
                                FROM    reboot_creator
                                WHERE   ID=$hashrow{id}
                                AND     location='$hashrow{dc__publisher}'
        ");
		$st2->execute();
		$hashrow{'creator'} = "";
        while(@row2=$st2->fetchrow()) {
			$hashrow{'creator'} .= "$row2[1]: $row2[0]\n" if($row2[0]);
        }
        $st2->finish();

		$hashrow{dc_title} .= "; $hashrow{dc__title__alternative}" if($hashrow{dc__title__alternative});
		$hashrow{dc_rights} .= "; $hashrow{dc__rights__license}" if($hashrow{dc__rights__license});
		$hashrow{dc__format} = "$hashrow{dc__format__extent}, $hashrow{dc__format__medium}, $hashrow{dc__format__encoding}";

		$rss->add_item(
			title       => $hashrow{dc__title},
			link        => URI->new($file),
			description => $hashrow{dc__description__long},
			dc => {
#				date_created     => $hashrow{dc__date__created},
				date    => eval { my $t=HTTP::Date::time2isoz($hashrow{dc__date__issued}); $t=~s/\ /T/; $t; },
				creator  => $hashrow{creator},
				subject  => $hashrow{dc__subject},
				type     => $hashrow{dc__type},
				title    => $hashrow{dc__title},
				publisher     => $hashrow{dc__publisher},
				format     => $hashrow{dc__format},
				rights     => $hashrow{dc__rights},
				identifier  => $hashrow{dc__identifier},
			},
			taxo => [
				'http://dmoz.org/Arts/Radio'
			]
		);
	}
    $st->finish();
    return($rss->as_string);
}



sub getnode {
	local $type = shift;
	local $genre = `grep -m 1 "~$type~" CAT | cut -d":" -f1`;
	chop($genre);
	local %node;

	$node{"misc"} = 12001;
	$node{"misc/experimental"} = 13001;
	$node{"misc/other"} = 14001;
	$node{"misc/radio art"} = 15001;
	$node{"music"} = 16001;
	$node{"music/electronic"} = 17001;
	$node{"music/experimental"} = 18001;
	$node{"music/techno"} = 19001;
	$node{"word"} = 20001;
	$node{"word+music"} = 21001;
	$node{"word+music/fanzine"} = 22001;
	$node{"word+music/radio play"} = 23001;
	$node{"word+music/radio show"} = 24001;
	$node{"word/experimental"} = 25001;
	$node{"word/news"} = 26001;
	$node{"word/radio play"} = 27001;
	$node{"word/talk"} = 28001;


	if(!$genre) {
		return($node{"misc"});
	}

	return($node{$genre});
}

sub parsetag {
	local $xmltext = shift;
	local $op = shift;	
	local $id = shift;
	local $base = shift;

	$cn1 = $cn2 = $cn3 = 0;
	local @xmlarr = split(/(\r|\n)/,$xmltext);
	$xmltext = join("\n",@xmlarr);

#	print $xmltxt;
#	for($i=0;$i<=$#xmlarr;$i++) { print "$xmlarr[$i]\n"; }

	local $p = XML::Parser->new(Style => 'Stream', ProtocolEncoding => 'UTF-8');
	local $doc = $p->parse($xmltext);

	local $tmp;
	local @counter;

	undef(@counter);
	undef(%count);

	local $ctype;
	local $cattr;
	local $ctag;
	local $identifierg;

	sub StartDocument {}
	sub EndTag {
		local $exp = shift;
		local $type = shift;
		local %attr = %_;
		local $tag = $_;

		$ctype = $cattr = $ctag = "";
	}

	sub Text {
		local $exp = shift;
		local $type = shift;
		local %attr = %_;
		local $tag = $_;

		local $sqlfield = $ctype;
		$sqlfield =~ s/:/__/g;
		if($sqlfield && $tag) {
			$tag =~ s/'/\\'/g;
			if($sqlfield eq "dc__contributor") {
				$cn1 = 0 if(!defined($cn1));

				if($cattr) {
					$sqlattr{"reboot_contributor$cn1"}[$count{"reboot_contributora$cn1"}] = $sqlfield ."__role";
					$sqlval{"reboot_contributor$cn1"}[$count{"reboot_contributor$cn1"}++]="'$cattr'";
					if($cattr eq "Importer") {
						$importer = $tag;
					}
				}

				$sqlattr{"reboot_contributor$cn1"}[$count{"reboot_contributor$cn1"}]=$sqlfield;
				$sqlval{"reboot_contributor$cn1"}[$count{"reboot_contributor$cn1"}++]="'$tag'";
				$cn1++;

			} elsif($sqlfield eq "dc__creator") {
				$cn2 = 0 if(!defined($cn2));

				if($cattr) {
					$sqlattr{"reboot_creator$cn2"}[$count{"reboot_creator$cn2"}]=$sqlfield ."__role";
					$sqlval{"reboot_creator$cn2"}[$count{"reboot_creator$cn2"}++]="'$cattr'";
				}

				$sqlattr{"reboot_creator$cn2"}[$count{"reboot_creator$cn2"}]=$sqlfield;
				$sqlval{"reboot_creator$cn2"}[$count{"reboot_creator$cn2"}++]="'$tag'";
				$cn2++;

			} elsif($sqlfield =~ /^dc__relation/) {
				$cn3 = 0 if(!defined($cn3));

				if($cattr) {
					$sqlattr{"reboot_relation$cn3"}[$count{"reboot_relation$cn3"}]=$sqlfield ."__role";
					$sqlval{"reboot_relation$cn3"}[$count{"reboot_relation$cn3"}++]="'$cattr'";
				}

				$sqlattr{"reboot_relation$cn3"}[$count{"reboot_relation$cn3"}]=$sqlfield;
				$sqlval{"reboot_relation$cn3"}[$count{"reboot_relation$cn3"}++]="'$tag'";
				$cn3++;

			} elsif($sqlfield =~ /^dc__/) {

				$sqlattr{'reboot_page'}[$count{'reboot_page'}]=$sqlfield;

				if($sqlfield eq "dc__date__issued") { $newid = $tag; }
				if($sqlfield eq "dc__title") { $title = $tag; }
				if($sqlfield eq "dc__title__alternative") { $alttitle = $tag; }
				if($sqlfield eq "dc__type") { $branch = "/Container$tag"; }

				if($sqlfield =~ /^dc__format__extent/) {
					$sqlval{'reboot_page'}[$count{'reboot_page'}++]="$tag";
				} elsif($sqlfield eq "dc__identifier") {
					my @t = split(/\//,$tag);
					$tag = $t[$#t];
					@t = split(/\\/,$tag);
					$tag = $t[$#t];
					$identifier = $tag;
					$sqlval{'reboot_page'}[$count{'reboot_page'}++]="'$tag'";
				} elsif($sqlfield eq "dc__date__created") {
					$sqlval{'reboot_page'}[$count{'reboot_page'}++]=str2time($tag);
				} else {
					$sqlval{'reboot_page'}[$count{'reboot_page'}++]="'$tag'";
				}

			}
		}
	}

	sub StartTag {
		local $exp = shift;
		local $type = shift;
		local %attr = %_;
		local $tag = $_;
		local $otag = $tag;

		chop($otag);

		$ctype = $type;
		$cattr = $attr{'role'};
		$ctag = $tag;

	}

	$sqlcmd ="";
	foreach $k (keys %sqlattr) {
		$tmp = $sqlattr{$k};
		@counter = @$tmp;
		if(!$title && $alttitle) {
			$title = $alttitle;
		}

		if($op eq "insert") {
			$newid = time;
			if($k eq "reboot_page") {
				$sqlcmd .= "\nINSERT INTO $k ( ID, location, dc__publisher, username, expire, path, dc__date__digitized, ";
			} elsif ($k =~ /^reboot_contributor/ ||
					 $k =~ /^reboot_creator/ ||
                     $k =~ /^reboot_relation/) {
				my $nk = $k; chop($nk);
				$sqlcmd .= "\nINSERT INTO $nk ( ID, location, ";
			} else {
				$sqlcmd .= "\nINSERT INTO $k ( ID, location, ";
			}
			for($i=0;$i<=$#counter;$i++) {
				 $sqlcmd .= "$sqlattr{$k}[$i],";
			}
			$sqlcmd =~ s/,$/\)/;
			$sqlcmd .= "\nVALUES ( ";
			if($k eq "reboot_page") {
				$sqlcmd .= "$newid,'archive.reboot.fm','archive.reboot.fm','$importer',0,'/REBOOT-DATA/',$newid,";
			} else {
				$sqlcmd .= "$newid,'archive.reboot.fm',";
			}
			for($i=0;$i<=$#counter;$i++) {
				$sqlcmd .= "$sqlval{$k}[$i],";
			}
			$sqlcmd =~ s/,$/\);\n/;
			if($k eq "reboot_page") {
				do {
					$newsid = OMA::nextsid("item_sid");
				} while($newsid < 10);
				$node = OMA::getnode($branch);
				if(!$node) {
					OMA::makebranch($branch);
					$node = OMA::getnode($branch);
				}
				$sqlcmd .= "\nINSERT INTO item VALUES ($newsid, $node, '$title', 'reboot', 0, 1);\n\n";
				$sqlcmd .= "INSERT INTO reboot_conn VALUES ($newsid,$newid,'archive.reboot.fm',0,$newsid);\n\n";
				mkdir("$REBOOT::REBOOT_PATH$newid",0775) or die "Can't create desired directory";
#				system("mv /opt/oma/incoming/$id-$identifier $REBOOT::REBOOT_PATH$newid/$identifier");
				system("mv /opt/oma/incoming/protor-$identifier $REBOOT::REBOOT_PATH$newid/$identifier");
			}
		} elsif($op eq "update") {
			$sqlcmd .= "\nUPDATE $k SET\n";
			for($i=0;$i<=$#counter;$i++) {
				 $sqlcmd .= "$sqlattr{$k}[$i]=$sqlval{$k}[$i],";
			}
			$sqlcmd =~ s/,$/\n/;
			$sqlcmd .= "WHERE ID=$id AND location='$base';\n";
		}
	}
	undef(@counter);
	undef(%count);
	undef(%sqlattr);
	undef(%sqlval);
	return(Encode::encode("utf8",$sqlcmd));
}


sub send_dc_set {
	local $serv = shift;
	local $id = shift;
	local $base = shift;

	LOG("catch request: send_dc_set: id=$id base=$base");
print "WASN JETZ\n";
	$t = REBOOTPARSE::generate_output($id,$base,3);
print "UNGLAAAAAAUBLICH\n";
#	$t = parsetag($t,"clean");
	$t = Encode::encode("utf8",$t);

	return($t);
}

sub receive_dc_set {
	local $serv = shift;
	local $dc_set = shift;
	local $username = shift;

	LOG("catch request: receive_dc_set: dc_set=$dc_set username=$username");
	local $sqlcmd = parsetag($dc_set,"insert",$username);
	$sqlcmd =~ s/dc__description__tableOfContent/dc__description__toc/;
	LOG("cmd: $sqlcmd");
	$st=$db->prepare($sqlcmd);
	$st->execute();

	return("ok.");
}

sub update_dc_set {
	local $serv = shift;
	local $dc_set = shift;
	local $id = shift;
	local $base = shift;

	LOG("catch request: update_dc_set: dc_set=$dc_set id=$id base=$base");
	local $sqlcmd = parsetag($dc_set,"update",$id,$base);

	return("ok.");
}

sub latest_at {
	local $serv = shift;
	local $node = shift;

	LOG("catch request: latest_at: node=$node");
	$st = $db->prepare("SELECT node FROM treemap WHERE sid=$node");
	$st->execute();
	@row = $st->fetchrow();
	$st->finish;
	$path = $row[0];

	return("<thatsit/>") if($node<1);

#	local @a = latest($node,"reboot_page.ID DESC");
	local $list =  latest_rss($node, $path);
	return(Encode::encode("utf8",$list));
#	return($list);
}

sub get_program_files {
	local $serv = shift;
	local $container = shift;
	local $program = shift;
	local $path = "/Container/$container/$program";
print "openacs connection detected, request $path\n";
	local $node = OMA::getnode($path);
	local @ret;
	local $i=0;

	LOG("catch request: get_program_files container=$container program=$program");
	if($node > 0) {
    	$st = $db->prepare("
			SELECT reboot_page.*
			FROM  item, reboot_conn, reboot_page
			WHERE item.node_sid = $node
			AND   item.type='reboot'
			AND   ( item.sid = reboot_conn.item_sid
			OR		item.link_item = reboot_conn.item_sid )
			AND   reboot_conn.reboot_page = reboot_page.ID
			AND   reboot_conn.location = reboot_page.location
			ORDER BY reboot_page.ID DESC
		");
		$st->execute();
		$st->bind_columns(\(@hashrow{@{$st->{NAME_lc}}}));
		while(@row=$st->fetchrow()) {
			my %hash;
			my @t = split(/\//,$hashrow{'dc__identifier'});
			$hash{'filename'} = "$hashrow{dc__title__alternative} / $hashrow{dc__title} ($t[$#t])";
#			$hash{'oma_url'} = "http://archive.reboot.fm/reboot-perl/reboot-player.m3u?id=$hashrow{'id'}&base=$hashrow{'location'}";

			$hash{'oma_url'} = "http://archive.reboot.fm$hashrow{'path'}$hashrow{'id'}/$t[$#t]";
			$hash{'dc__title'} = $hashrow{dc__title};
			$hash{'dc__title__alternative'} = $hashrow{dc__title__alternative};
			my $date=HTTP::Date::time2isoz($hashrow{'dc__date__digitized'});
			$date=~s/\ /T/;
			$hash{'dc__date__digitized'} = $date;
			$ret[$i++] = \%hash;
		}
		$st->finish();
	}
	return(\@ret);
}

if(! -f "/opt/oma/omarpcserver.log") {
	my $now = strftime "%Y-%b-%e %H:%M:%S", localtime;
	open(F,"> /opt/oma/omarpcserver.log");
	print F "$now: omarpcserver.log created";
	close(F);
} else {
	LOG "omarpcserver.log created";
}

$srv = new RPC::XML::Server->new(host => '0.0.0.0', port => 9500) || die("cant start server");
$srv->compress_thresh(10000000);


$srv->add_method({  name => 'oma.send_dc_set',
        signature => [ 'string int string' ],
        code => sub { return(send_dc_set($_[0],$_[1],$_[2])); }
        }
);

$srv->add_method({  name => 'oma.receive_dc_set',
        signature => [ 'string string string' ],
        code => sub { return(receive_dc_set($_[0],$_[1],$_[2])); }
        }
);

$srv->add_method({  name => 'oma.update_dc_set',
        signature => [ 'string string int string' ],
        code => sub { return(update_dc_set($_[0],$_[1],$_[2],$_[3])); }
        }
);
$srv->add_method({  name => 'oma.latest_at',
        signature => [ 'string int' ],
        code => sub { return(latest_at($_[0],$_[1])); }
        }
);
$srv->add_method({  name => 'oma.get_program_files',
        signature => [ 'string string string' ],
        code => sub { return(get_program_files($_[0],$_[1],$_[2])); }
        }
);


$srv->server_loop; # Stays in an accept/connect loop
