#! /usr/local/bin/perl
# <Christian.Queinnec@lip6.fr>
# Syntax: write-ical [~/.calendar] ...
#
# This one-shot perl script converts my calendar from Ical (running on a
# workstation) to a PalmIII. I used it only once. 
#
# Restrictions: This script does not handle repetitions at all (they
# cannot be specified in the format of install-book). Notes are
# converted into appointments.

#     This program is free software; you can redistribute it and/or modify
#     it under the terms of the GNU General Public License as published by
#     the Free Software Foundation; either version 2 of the License, or
#     (at your option) any later version.

#     This program is distributed in the hope that it will be useful,
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#     GNU General Public License for more details.

#     You should have received a copy of the GNU General Public License
#     along with this program; if not, write to the Free Software
#     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

# Set this variable:
my $timeZone = "CET";

use diagnostics;
diagnostics::enable();

my $verbose = 0;

my $pilotFile = "/tmp/ical.tmp";

if ( $#ARGV == -1 ) {
    @ARGV = ( $ENV{'HOME'}."/.calendar" );
}

sub transform_into_hour {
    local($_) = @_;
    my($h) = int ($_ / 60);
    my($m) = $_ % 60;
    return $h . ":" . $m . " " . $timeZone;
}

open(TOPILOT, "> $pilotFile")
    || die "Cannot write into $pilotFile.";

undef $/;
$_ = <>;

# Skip the header until the first entry:
s/Calendar(.*?)\n(Appt|Note)/$2/s;

while ( s/\n(Note|Appt)\s*\[\s*(.*?\s*\])\n\]//s ) {
    # Found an entry, parse it:
    my($type) = $1;
    local($_) = $2;
    my($start, $length, $uid, $owner, $remind, $hilite, $text);
    my($textLength, $alarms, $pilotrecordid, $startHour, $endHour, $alarmHour);
    my($day, $month, $year, $repeatMonth, $repeatDay);
    print ">>", $_, "<<\n" if $verbose>5;
    if ( s/Uid\s*\[(.*?)\]\s*// ) {
        $uid = $1;
    } else {
        die "Record without Uid: $_";
    }
    if ( s/Start\s*\[(\d+)\]\s*// ) {
        $start = $1;
        $startHour = transform_into_hour($start);
    }
    if ( s/Length\s*\[(\d+)\]\s*// ) {
        $length = $1;
    }
    if ( s/PilotRecordId\s*\[(.*?)\]\s*// ) {
        $pilotrecordid = $1;
    }
    if ( s/Owner\s*\[(.*?)\]\s*// ) {
        $owner = $1;
    }
    if ( s/Remind\s*\[(.*?)\]\s*// ) {
        $remind = $1;
    }
    if ( s/Hilite\s*\[(.*?)\]\s*// ) {
        $hilite = $1;
    }
    if ( s/Alarms\s*\[(.*?)\]\s*// ) {
        local($_) = $1;
        $alarms = 0;
        while ( s/(\d+)\s*// ) {
            $alarms = $1;
            $alarmHour = $alarms . "m";
        }
    }
    if ( s/Text\s*\[(\d+)\s*\[// ) {
        $textLength = $1;
        $text = substr $_, 0, $textLength;
        $_ = substr $_, $textLength;
        s/^\]\]//;
        print "\n$text\n" if $verbose>2;
    }
    if ( s/Contents\s*\[(.*?)\]//s ) {
        if ( $text ) {
            die "Handling $uid, simultaneous Text and Contents.";
        } else {
            $text = $1;
        }
    }
    if ( s/Dates\s*\[(.*?)\]\s*//s ) {
        local($_) = $1;
        if ( /^Single\s+(\d+)\/(\d+)\/(\d+)\s*End$/ ) {
            $day = $1;
            $month = $2;
            $year = $3;
        } elsif ( /^Months\s+(\d+)\/(\d+)\/(\d+)\s+(\d+)\s*.*End$/s ) {
            $day = $1;
            $month = $2;
            $year = $3;
            $repeatMonth = $4; # by month     Ignored for now FUTURE
        } elsif ( /^Days\s+(\d+)\/(\d+)\/(\d+)\s+(\d+)\s*.*End$/s ) {
            $day = $1;
            $month = $2;
            $year = $3;
            $repeatDay = $4; # by day         Ignored for now FUTURE
        } else {
            die "Handling $uid, unrecognized Dates: $_.";
        }
    }
    # Compute deduced variables:
    if ( $type eq "Appt" ) {
        if ( defined $start && defined $length ) {
            $endHour = transform_into_hour($start + $length);
        } else {
            die "Handling $uid, missing Start and/or Length.";
        }
    }
    if ( $type eq "Appt" ) {
        $alarmHour = 5;
    } else {
        $alarmHour = '';
    }
    # Remove newlines from text:
    $text =~ s/\n/ /g;
    # Check if anything is left from the record:
    s/\s*//s;
    if ( $_ ) {
        die "Handling $uid, unprocessed: $_.";
    }
    # Check if main variables are defined:
    unless ( defined $startHour ) {
        die "Handling $uid, undefined startHour.";
    }
    unless ( defined $endHour ) {
        die "Handling $uid, undefined endHour.";
    }
    unless ( defined $alarmHour ) {
        die "Handling $uid, undefined alarmHour.";
    }
    unless ( defined $text ) {
        die "Handling $uid, undefined Text.";
    }
    # Generate a line for the date book:
    print TOPILOT "$year/$month/$day $startHour\t"
        . "$year/$month/$day $endHour\t"
        . $alarmHour . "m\t$text\n";
}

close(TOPILOT) 
    || die "Cannot close $pilotFile";

exec "install-datebook /dev/pilot $pilotFile"
    || die "Cannot run install-datebook.";

# end of write-ical.pl
