#!/usr/bin/perl -Tw

use LWP::Simple;
use HTML::Parser;

my $cachedir="/tmp/on.radio.cache";
my $outputdir="/tmp/streams";

my $URL="http://www.internode.on.net/residential/entertainment/broadband_radio/";
my $cachefile=$cachedir."/"."root";

-d $cachedir || die "Cache dir $cachedir does not exist\n";

use Data::Dumper;

# the pattern goes:
# td:CopySolidFirstColumn(a:StationURL,b:Title)
# td:CopySolidCell(Subtitle)
# td:CopySolidCell(bandwidth)
# td:CopySolidCell(a:StreamURL)

my $state=0;		# global
my $thistext="";	# global
my $thisclass="";
my @thislist=();	# global
my $neartables=0;	# global
my $thisTitle="";	# name of station
my $thisSubtitle="";	# name of station
my $thisURL="";
my $thisWebsite="";
my $thisBandwidth="";

my $suffix="m3u";

sub munge {
	# make a filename vfat-compatible
	my $fn=shift;
	$fn =~ s/['"~^\/!():]/_/g;
	$fn =~ /^(.*)$/;
	return $1;
}

sub fetch {
	my $url=shift;
	my $basename;
	($basename)=($url =~ /\/([^\/]*)$/);
	my $file=$cachedir."/".$basename;
	my $code=mirror($url,$file);
	return undef if is_error($code);
	open(FILE,"<$file") or die "open: $!: $file\n";
	while(<FILE>) {
		chomp;
		return $_ if $_ =~ /^http/;
	}
	return undef;
}

sub store {
	my($thisTitle, $thisSubtitle, $thisWebsite, $thisURL, $thisBandwidth)=@_;
	return unless defined $thisURL and length $thisURL;
	return unless defined $thisTitle and length $thisTitle;
	my $filename=$thisTitle.".".$suffix;
	$filename = munge($filename);
	print "$filename";
	my $fetch=fetch($thisURL);
	if (!defined($fetch)) {
		print " - failed\n";
		return undef;
	}
	print "\n";
	$filepath=$outputdir."/".$filename;
	open(FILE,">$filepath") or die "open: $!: $filepath\n";
	print FILE "#EXTM3U\n";
	print FILE "#EXTINF:-1,$thisTitle\n";
	#print FILE "#$thisSubtitle\n";
	#print FILE "#$thisWebsite\n";
	#print FILE "#$thisBandwidth\n";
	print FILE "$fetch\n";
	close(FILE) or die "close: $!: $filepath\n";
}

sub start {
	return unless $neartables;
	my ($tag,$attr,$text)=@_;
	if ($tag eq "a") {
		if ($state == 1) {
			$thisWebsite=$$attr{'href'};
			$state++;
		} elsif ($state == 9) {
			$thisURL=$$attr{'href'};
			$state++;
		}
	} elsif ($tag eq "b") {
		$state++ if $state==1;
	} elsif ($tag eq "td") {
		my $class=$$attr{'class'};
		if (defined($class)) {
			$state=1 if $class eq "CopySolidFirstColumn";
			$state++ if $state>=1 and $class eq "CopySolidCell";
			$thisclass=$class;
		}
	}
	$thistext="";
}

sub end {
	return unless $neartables;
	my ($tag,$attr,$text)=@_;
	if ($tag eq "td") {
		if ($state == 5) {
			$thisTitle =~ s/^\s+//;
			$thisTitle =~ s/\s+$//;
			chomp($thisTitle);
			$thisSubtitle =~ s/^\s+//;
			$thisSubtitle =~ s/\s+$//;
		}
		if ($state == 10) {
			store($thisTitle, $thisSubtitle, $thisWebsite, $thisURL, $thisBandwidth);
			$thisclass="";
			$thisTitle="";
			$thisSubtitle="";
			$thisURL="";
			$thisWebsite="";
			$thisBandwidth="";
			$state=0;
		}
		$state++ if $state >= 2;
	}
	$thistext="";
}

sub text {
	my ($tag,$attr,$text)=@_;
	$neartables++ if $text eq "Radio Station List";
	if ($state == 2) {
		$state++;
		$thisTitle=$text;
	} elsif ($state == 7) {
		$text =~ s/^\s+//;
		$text =~ s/\s+$//;
		$thisBandwidth = $text;
	} elsif ($state == 5) {
		$thisSubtitle .= $text;
	}
}

$code=mirror($URL,$cachefile);
die "Failed to fetch: $URL ($code)\n"
	if is_error($code);

my $parser=HTML::Parser->new(	api_version => 3,
				start_h => [\&start, "tagname, attr, dtext"],
				end_h => [\&end, "tagname, attr, dtext"],
				text_h => [\&text, "tagname, attr, dtext"],
				#marked_sections => 1,
			);

$parser->report_tags(qw(table td a b));

$parser->parse_file($cachefile);
