#!/usr/bin/env perl
# -*- perl -*-

#
# Author: Slaven Rezic
#
# Copyright (C) 2024 Slaven Rezic. All rights reserved.
# This program is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.
#
# Mail: slaven@rezic.de
# WWW:  http://www.rezic.de/eserte/
#

use strict;
use warnings;
use POSIX qw(strftime);

my $headline_start_rx = qr{^\*+\s+(TODO|DONE|WAITING|WONTFIX|LATER)\s+};

my @files = @ARGV;
if (!@files) {
    die "Please specify one or more org mode files.\n";
}

my @locations;

for my $file (@files) {
    open my $fh, '<:encoding(utf-8)', $file
	or die "Can't open $file: $!";
    my $active_headline;
    my $active_headline_is_TODO;
    while(<$fh>) {
	if (/$headline_start_rx/) {
	    $active_headline = $_;
	    $active_headline_is_TODO = $1 eq 'TODO';
	}
	if ($active_headline_is_TODO && m{\[\[geo:([-+]?\d+(?:\.\d+)?),([-+]?\d+(?:\.\d+)?)(?:\?z=(\d+(?:\.\d+)?))?\](?:\[(.*?)\])?\]}) {
	    my($lat, $lon, $zoom, $link_title) = ($1,$2,$3,$4); # $zoom not yet used
	    if (!defined $active_headline) {
		warn "Found geo URI for $lat/$lon, but without an associated org-mode headline, skipping...\n";
		next;
	    }
	    push @locations, {
		link_title => (defined $link_title ? $link_title : extract_headline($active_headline)),
		lon => $lon,
		lat => $lat,
	    };
	}
    }
}

if (!@locations) {
    die "No locations found in @files.\n";
}

binmode STDOUT, ':encoding(utf-8)';
print <<EOF;
#: encoding: utf-8
#: map: polar
#: 
# Converted from @files at @{[ strftime("%Y-%m-%d %H:%M:%S", localtime) ]}
# 
EOF
for my $location (@locations) {
    my $link_title = $location->{link_title};
    $link_title =~ s{[\t\n]}{ }g;
    print "$link_title\tX $location->{lon},$location->{lat}\n";
}

sub extract_headline {
    my $headline = shift;
    $headline =~ s{$headline_start_rx}{}; # TODO/DONE
    $headline =~ s{\[#A-F\]\s*}{}; # priority
    $headline =~ s{\s+:.*?:\s*$}{}; # tags
    $headline =~ s{^\s+}{}; $headline =~ s{\s+$}{}; # trim
    $headline;
}

__END__

=head1 NAME

org2bbd - find org-mode TODO items with geolocations and convert to bbd

=head1 SYNOPSIS

    org2bbd TODO.org > TODO.bbd

=head1 DESCRIPTION

Search for geo locations in emacs org-mode files (i.e. links in the
form C<< [[geo:lat,lon]] >>) and convert them into bbd data, which is
written to stdout.

Only items marked as C<TODO> are taken into account.

The bbd record name is the link name, if it exists, otherwise it's the
item headline (note: the latter might change in future).

=head2 EXAMPLES

To convert into a gpx file do something like the following:

    ./miscsrc/org2bbd /path/to/file.org | ./miscsrc/bbd2gpx - > /path/to/file.gpx

Same, but prettify the XML (requires C<xmllint>):

    ./miscsrc/org2bbd /path/to/file.org | ./miscsrc/bbd2gpx - | xmllint -format - > /path/to/file.gpx

=cut
