package NonameTV::Importer::ORF_xml;

use strict;
use warnings;

=pod

Importer for data from ORF.
The data is downloaded from ORF's presservice at http://presse.orf.at/
Every day is handled as a separate batch.

Channels: ORF1, ORF2, DreiSat, (a lot of radio stations)

=cut

use DateTime;
use HTTP::Date;
use XML::LibXML;
use utf8;

use NonameTV qw/ParseXml norm AddCategory/;
use NonameTV::DataStore::Helper;
use NonameTV::Log qw/w progress error f d/;

use NonameTV::Importer::BaseDaily;

use base 'NonameTV::Importer::BaseDaily';

sub new {
    my $proto = shift;
    my $class = ref($proto) || $proto;
    my $self  = $class->SUPER::new( @_ );
    bless ($self, $class);

    $self->{MinDays} = 0 unless defined $self->{MinDays};
    $self->{MaxDays} = 15 unless defined $self->{MaxDays};

    # consider less then or equal x programmes an error and keep the old data
    $self->{MinProgrammes} = 5 unless defined $self->{MinProgrammes};

    if( defined(  $self->{UrlRoot} ) ) {
      w( "UrlRoot is deprecated. No point in keeping it secret as it\'s login protected now. Set Username and Password instead." );
    } else {
      $self->{UrlRoot} = 'http://presse.orf.at/download.php?sender=';
    }

    defined( $self->{Username} ) or die "You must specify Username";
    defined( $self->{Password} ) or die "You must specify Password";

    my $dsh = NonameTV::DataStore::Helper->new( $self->{datastore}, "Europe/Vienna" );
    $self->{datastorehelper} = $dsh;

    $self->{datastore}->{augment} = 1;

    return $self;
}

sub InitiateDownload {
  my $self = shift;

  my $mech = $self->{cc}->UserAgent();

  my $response = $mech->get('http://presse.orf.at/?login[action]=login&login[redirect]=&login[username]=' . $self->{Username} . '&login[password]=' . $self->{Password});

  if ($response->is_success) {
    return undef;
  } else {
    return $response->status_line;
  }
}

sub Object2Url {
  my $self = shift;
  my( $objectname, $chd ) = @_;

  my( $year, $month, $day ) = ( $objectname =~ /(\d+)-(\d+)-(\d+)$/ );
 
  my( $channel, @flags ) = split( /,\s*/, $chd->{grabber_info} );

  my $url = $self->{UrlRoot} .
    $channel . '&date=' . $year . $month . $day;

  return( $url, undef );
}

sub FilterContent {
  my $self = shift;
  my( $cref, $chd ) = @_;

  my( $chid ) = ($chd->{grabber_info} =~ /^(\d+)/);
  my( $channel, @flags ) = split( /,\s*/, $chd->{grabber_info} );

  my $orf2europe = 0;
  foreach my $flag (@flags) {
    if( $flag eq 'orf2europe' ) {
      $orf2europe = 1;
    }
  }
  

  my $doc;
  $$cref =~ s|encoding="LATIN1"|encoding="windows-1252"|;
  $$cref =~ s|<programmablauf>\n</programmtag>|<programmablauf>\n<programmtag />|s;
  $doc = ParseXml( $cref );

  if( not defined $doc ) {
    return (undef, "ParseXml failed" );
  }

  # Find all "Schedule"-entries.
  my $ns = $doc->find( "//sendung" );

  if( $ns->size() <= $self->{MinProgrammes} ) {
    # TODO sometimes there seem to be no programs on sportplus
    return (undef, 'Aborting because only ' . $ns->size() . ' programmes have been found.' );
  }

  if( $orf2europe == 1 ){
    my $nodes = $doc->find( "//sendung[o2e='FALSE']/titel" );
    foreach my $node ($nodes->get_nodelist) {
      $node->removeChildNodes();
      $node->appendTextNode( 'end-of-transmission' );
    }
    $nodes = $doc->find( "//sendung[o2e='FALSE']/info" );
    foreach my $node ($nodes->get_nodelist) {
      $node->removeChildNodes();
    }
  }

  my $str = $doc->toString( 1 );

  return( \$str, undef );
}

sub ContentExtension {
  return 'xml';
}

sub FilteredExtension {
  return 'xml';
}

my %genrewords = (
	'Abenteuerserie' => 1,
	'Actionserie' => 1,
	'Action-Drama-Serie' => 1,
	'Animation' => 1,
	'Anwaltsserie' => 1,
	'Comedyserie' => 1,
	'Familienserie' => 1,
	'Jugendserie' => 1,
	'Kriminalserie' => 1,
	'Krimiserie' => 1,
	'Medical Daily' => 1,
	'Mysteryserie' => 1,
	'Ratespiel mit Elton' => 1,
	'Serie' => 1,
	'Sitcom' => 1,
	'Stop Motion Trick' => 1,
	'Talk-Show mit Barbara Karlich' => 1,
	'Telenovela' => 1,
	'Unterhaltungsserie' => 1,
	'Zeichentrickserie' => 1,
);


sub ImportContent
{
  my $self = shift;

  my( $batch_id, $cref, $chd ) = @_;

  my $ds = $self->{datastore};
  my $dsh = $self->{datastorehelper};
  
  $ds->{SILENCE_END_START_OVERLAP}=1;
  $ds->{SILENCE_DUPLICATE_SKIP}=1;
 
  my $xml = XML::LibXML->new;
  my $doc;
  eval { $doc = $xml->parse_string($$cref); };
  if( $@ ne "" )
  {
    f "Failed to parse $@";
    return 0;
  }
  	my( $date ) = ($batch_id =~ /_(.*)$/);
	
	$dsh->StartDate( $date , "00:00" );
 
 	 # Find all "z:row"-entries.
 	 my $ns = $doc->find( "//sendung" );

 	 if( $ns->size() == 0 )
 	 {
 	   f "No data found";
 	   return 0;
 	 }
  
  	 
 	 foreach my $sc ($ns->get_nodelist)
  	{

	
	my $title = $sc->findvalue( './titel' );
	

   	 my $time = ParseTime( $sc->findvalue( './zeit' ) );


		d( "ORF_xml: $chd->{xmltvid}: $time - $title" );

  		my $ce = {
  	      title 	  => norm($title),
 	      start_time  => $time,
   		};
   	 
  	  	my @descnodes = $sc->findnodes( './info' );
                foreach my $node (@descnodes) {
                my $desc = $node->textContent();
		# strip repeat
		$desc =~ s|\(Wh\..+?\)||;
		my( $genre, $countries, $year )=( $desc =~ m|\((.+?), (\S+) (\d{4})\)| );
		if( $year ){
			$desc =~ s|\(.+?, .+? \d{4}\)||;
			$ce->{production_date} = $year . '-01-01';

			# split optional "original title - genre"
			$genre =~ s|^.+ - (.+?)$|$1|;
			my ( $program_type, $categ ) = $self->{datastore}->LookupCat( "ORF", $genre );
			# set category, unless category is already set!
			AddCategory( $ce, $program_type, $categ );
			AddCategory( $ce, 'movie', undef );
		}else{
			my( $genreword )=( $desc =~ m/^(.*?)(?:\n|$)/s );
			if( $genreword ){
				if( $genrewords{$genreword} ) {
					$desc =~ s/^.*?(?:\n|$)//s;
					my ( $program_type, $categ ) = $self->{datastore}->LookupCat( "ORF", $genreword );
					AddCategory( $ce, $program_type, $categ );
				}
			}
		}

		# TODO handle more jobs
		# Analytiker: Günther Neukirchner
		# Buch: Verena Kurth
		# Co-Kommentator: Alexander Wurz
		# Kommentator: Ernst Hausleitner
		# Moderation: Markus Mooslechner
		# Präsentator: Boris Kastner-Jirka
		# Ratespiel mit Elton Co-Produktion ZDF/ORF
		# 

		# not actors: Mit welchen Psychotricks werden wir beeinflusst, ohne es zu merken?
		my( $actors )=( $desc =~ m|^M[Ii]t ([A-Z].+?)$|m );
		if( $actors ){
			$desc =~ s|^M[Ii]t .+?$||m;
			$actors =~ s| u\.a\.$||;
			# TODO clean up the list of actors
                        $actors =~ s|,\s*,|,|g; # remove empty elements from the list
			$ce->{actors} = parse_person_list($actors);
		}
		my( $directors )=( $desc =~ m|^Regie:\s+(.+?)$|m );
		if( $directors ){
			$desc =~ s|^Regie:\s+.+?$||m;
			# TODO clean up the list of directors
                        $directors = norm( $directors );
			$ce->{directors} = parse_person_list($directors);
		}
		my( $running_time )=( $desc =~ m|^(\d+\.\d+)$|m );
		if( $running_time ){
			$desc =~ s|^\d+\.\d+$||m;
			# TODO do we want to add running time?
		}
		( $running_time )=( $desc =~ m|^ca. (\d+)\'$|m );
		if( $running_time ){
			$desc =~ s|^ca. \d+\'$||m;
			# TODO do we want to add running time?
		}
                # just a remark, not a programm description => remove it
                if( $desc =~ m|^\s*\(.*\)\s*$| ){
                        $desc = '';
                }
                if( $desc ) {
                       if( $desc =~ m|^\s*Details folgen!\s*$| ) {
                              $desc = undef;
                       }
                }
                if( $desc ){
                       $ce->{description} = norm($desc);
                }
                }

		my $subtitle =  $sc->findvalue( './subtitel' );
                if( $subtitle =~ m|\s+/\s+ENTFALLEN$| ){
                        $ce->{title} = 'end-of-transmission';
                        $subtitle =~ s|\s+/\s+ENTFALLEN$||;
                }
                $subtitle =~ s|\s+\(Wh\.\)$||;
                $subtitle =~ s|^\s*Titel folgt\s*$||;
		if( $subtitle =~ m/^(?:Folge|Kapitel|Teil)\s+\d+\s+-\s+.+$/ ){
			my( $episodenum, $episodetitle )=( $subtitle =~ m/^(?:Folge|Kapitel|Teil)\s+(\d+)\s+-\s+(.+)$/ );
			$ce->{episode} = '. ' . ($episodenum - 1) . ' .';
	   	 	$ce->{subtitle} = norm( $episodetitle );
		}elsif( $subtitle =~ m/^(?:Folge|Kapitel|Teil)\s+\d+$/ ){
			my( $episodenum )=( $subtitle =~ m/^(?:Folge|Kapitel|Teil)\s+(\d+)$/ );
			$ce->{episode} = '. ' . ($episodenum - 1) . ' .';
		}elsif( $subtitle ){
	   	 	$ce->{subtitle} = norm( $subtitle );
		}
	
		my $stereo =  $sc->findvalue( './m' );
		if( $stereo eq 'True' ){
   	 		$ce->{stereo} = 'mono';
		}

		$stereo =  $sc->findvalue( './s' );
		if( $stereo eq 'True' ){
   	 		$ce->{stereo} = 'stereo';
		}

		# dolby surround sound
		$stereo =  $sc->findvalue( './dss' );
		if( $stereo eq 'True' ){
   	 		$ce->{stereo} = 'surround';
		}

		# dolby digital surround / AC-3 5.1
		$stereo =  $sc->findvalue( './dds' );
		if( $stereo eq 'True' ){
   	 		$ce->{stereo} = 'dolby digital';
		}

		$stereo =  $sc->findvalue( './zs' );
		if( $stereo eq 'True' ){
   	 		$ce->{stereo} = 'bilingual';
		}

		my $widescreen =  $sc->findvalue( './bb' );
		if( $widescreen eq 'True' ){
   	 		$ce->{aspect} = '16:9';
		}

#		my $captions =  $sc->findvalue( './ut' );
#		if( $captions eq 'True' ){
#   	 		$ce->{captions} = 'teletext';
#		}

		# TODO how does ORF signal HD? just slap quality=HDTV on everything on channels with xmltvid hd.*
		if( $chd->{xmltvid} =~ m|^hd\.| ){
			$ce->{quality} = 'HDTV';
		}
	
  	  $dsh->AddProgramme( $ce );
 	 }
  
  # Success
  return 1;
}

sub parse_person_list
{
  my( $str ) = @_;

  my @persons = split( /\s*,\s*/, $str );
  foreach (@persons)
  {
    # The character name is sometimes given . Remove it.
    s/^.*\s+-\s+//;
  }

  return join( ";", grep( /\S/, @persons ) );
}

sub ParseTime {
  my( $text ) = @_;

  my( $hour , $min );

  if( $text =~ /^\d+:\d+$/ ){
    ( $hour , $min ) = ( $text =~ /^(\d+):(\d+)$/ );
  }
  
  return sprintf( "%02d:%02d", $hour, $min );
}
    
1;
