#!/usr/bin/perl -w

use DateTime;
use DateTime::TimeZone;
use DateTime::Format::ISO8601;
use DateTime::Format::Strptime;

$MINIMAL_COUNT = "10";

sub Usage {
    print "\nadas_ascii2xml <current date>\n\n";
    print "Options:\n";
    print "  -i <installation_id>\n";
    print "  -l <layout_id>\n";
    print "  -c <configuration_id>\n";
    print "  -t<a|x> <ASCII or XML file time zone>\n";
    print "     Use '+5:00' to set GMT offset\n";
    print "     Use 'system' to use system timezone\n";
    print "\n";
    print "Examples:\n";
    print "  adas_ascii2xml 2006-05-31\n";
    print "\n";
}

sub get_seconds {
    $duration = $_[0];
    my ($min, $secs) = $duration->in_units('minutes', 'seconds');
    return $min * 60 + $secs;
}

sub ParseTZ {
    my $tz = shift;
    
    if (!($tz cmp "GMT")) { return "UTC"; }
    if ($tz =~ /system/) { return "local"; }
    
    if ($tz =~ /^(GMT|UTC)([+\-]\d+:\d+)$/) { return $2; }
    if ($tz =~ /^(GMT|UTC)([+\-]\d+)$/) { return $2 . ":00"; }

    return "GMT";
}


my $installation = "";
my $layout = "";
my $configuration = "";
my $timezone = DateTime::TimeZone->new(name=>'UTC');
my $xml_timezone = DateTime::TimeZone->new(name=>'local');

while ($#ARGV>=0) {
    my $param = shift @ARGV;
    if ($param =~ m/^-/) {
	if (!($param cmp "-i")) { $installation = shift(@ARGV); }
	elsif (!($param cmp "-l")) { $layout = shift(@ARGV); }
	elsif (!($param cmp "-c")) { $configuration = shift(@ARGV); }
	elsif (!($param cmp "-ta")) { 
	    $tz = ParseTZ(shift(@ARGV)); 
	    $timezone = DateTime::TimeZone->new(name=>$tz);
	    
	} elsif (!($param cmp "-tx")) { 
	    $tz = ParseTZ(shift(@ARGV)); 
	    $xml_timezone = DateTime::TimeZone->new(name=>$tz);
	} else {
	    print "Invalid option: $param\n";
	    Usage();
	    exit;
	}
    } else {
	if (defined($filedate)) {
	    print "Unknown option: \"$param\" or \"$filedate\"\n";
	    Usage();
	    exit;
	}
	$filedate = $param;
    }
}

if (!$filedate) {
    Usage();
    exit;
}

while (<>) {
    $data .= $_;
}

my @records = split /\n\s*/, $data;
my @badlines;

my $isoparser = DateTime::Format::ISO8601->new();
my $ascparser = DateTime::Format::Strptime->new( pattern => '%Y-%m-%d %H:%M:%S' );

my @vectors;
foreach $rec(@records) {
    if ($rec =~ /[^\s\d\:.Ee+\-]/) { next; }
    ($time, $data) = split /\s+/, $rec, 2;
    $tm =  $ascparser->parse_datetime($filedate . " " . $time);
    if ($tm) {
	$tm->set_time_zone($timezone);
	
	%item = ( 'time', $tm, 'data', $data );
	push (@vectors,  { %item });
    } 
#    else {
#	if (!$invrec) {
#	    print STDERR "Invalid records:\n\n";
#	    $invrec = 1;
#	}
#	print STDERR $rec . "\n";
#    }
}
#if ($invrec) { exit; }

undef(%item);
$last_start = 0;
$last_duration = 0;
$last_count = 0;

my @intervals;
for ($i=0;$i<$#vectors;$i++) {
        $duration = $vectors[$i+1]->{'time'}->subtract_datetime($vectors[$i]->{'time'});
	$secs = get_seconds($duration);
	if ($secs == $last_duration) { $last_count++; }
	else {
	    if ($last_count < $MINIMAL_COUNT) {
		if ((defined(%item))&&($item{'duration'}==$secs)) {
		    $last_start = $item{'time'};
		    $last_count = $item{'count'} + 1;
		    $last_duration = $item{'duration'};
		    pop(@intervals);
		} else {
		    $last_start = $vectors[$i]->{'time'};
		    $last_duration = $secs;
		    $last_count = 1;
		}
	    } else {
		%item = ( 'time', $last_start, 'count', $last_count, 'duration', $last_duration );
		push (@intervals,  { %item });
		$last_start = $vectors[$i]->{'time'};
		$last_duration = $secs;
		$last_count = 1;
	    }
	}
}

if ($last_count >= $MINIMAL_COUNT) {
    %item = ( 'time', $last_start, 'count', $last_count, 'duration', $last_duration );
    push (@intervals,  { %item });
}

if (!@intervals) {
    print STDERR "Broken data file. The impossible to detect time intervals.\n";
    exit;
}

$intervals[0]->{'time'} = $vectors[0]->{'time'};

#for ($i=0;$i<=$#intervals;$i++) {
#    print $intervals[$i]->{'time'} . " : " . $intervals[$i]->{'duration'} . ".\n";
#}

#$intervals[1]->{'time'} = $vectors[600]->{'time'};
#$intervals[1]->{'duration'} = 600;

$curinterval = 0;
foreach $vector(@vectors) {
    $time = $vector->{'time'};
    if ((defined($intervals[$curinterval+1]))&&(DateTime->compare($time, $intervals[$curinterval+1]->{'time'})>=0)) {
	$curinterval++;
    }
    
    $duration = $intervals[$curinterval]->{'duration'};    


    $time->set_time_zone($xml_timezone);
    
    
#    $time->set_formatter( $isoparser );
    $isotime = $time->strftime('%Y-%m-%dT%H:%M:%S.0000000');

    $tz = $xml_timezone->offset_for_datetime($time);
    if ($tz>0) {
	$tzh = $tz / 3600;
	$tzm = ($tz - $tzh*3600)/60;
	if ($tzh<10) { $tzh = "0" . $tzh; }
	if ($tzm<10) { $tzm = "0" . $tzm; }
	$isotime .= "+" . $tzh . ":" . $tzm;
    } elsif ($tz<0) {
	$tzh = abs($tz) / 3600;
	$tzm = (abs($tz) - $tzh*3600)/60;
	if ($tzh<10) { $tzh = "0" . $tzh; }
	if ($tzm<10) { $tzm = "0" . $tzm; }
	$isotime .= "-" . $tzh . ":" . $tzm;
    } else {
	$isotime .= "Z";
    }
    
    print "<Data installation=\"$installation\" layout=\"$layout\" configuration=\"$configuration\">\n";
    print "  <Time>$isotime</Time>\n";
    print "  <Quality>100.00</Quality>\n";
    print "  <Duration>P$duration.0000000</Duration>\n";
    print "  <Value>$vector->{'data'}</Value>\n";
    print "</Data>\n";
}

