#!/usr/bin/perl -w
#
# command line interface to knotes via DCOP
#
use Getopt::Long;

# the CPAN-provided DCOP is awful: it uses backticks to do the heavy
# lifting, so you need to preprocess any data you hand to it to remove
# dangerous things like, well, more backticks. So I'm fixing it
# in-line here.
package DCOP;
use strict;
use warnings;

our $VERSION = '0.037';

sub new() {
    my $proto  = shift;
    my $class  = ref( $proto ) || $proto;
    my %params = @_;
    my $self   = {};
    $self->{ start }    = localtime;
    $self->{ user }     = $params{ user }    if ( $params{ user } );
    $self->{ target }   = $params{ target }  if ( $params{ target } );
    $self->{ control }  = $params{ control } if ( $params{ control } );
    chomp( my $basepath = `kde-config --expandvars --exec-prefix` );
    $self->{ dcop }  = "$basepath/bin/dcop ";
    $self->{ dcop } .= "--user $self->{user} " if ( $self->{ user } );
    $self->{ dcop } .= "$self->{target} "      if ( $self->{ target } );
    $self->{ dcop } .= "$self->{control} "     if ( $self->{ control } );
    bless( $self, $class );
    return $self;
}

sub run() {
    my $self = shift;

    my $ret = "";
    my $pid = open( DCOP, "-|" );
    if ( $pid ) {
        while ( <DCOP> ) {
            $ret .= $_;
        }
        close( DCOP ) or warn "dcop exited $?";
        chomp( $ret );
    } else {
        my ( $prog, @args ) = split( ' ', $self->{dcop} );

        # this isn't entirely compatible with the old code: you'll need to
        # pass individiual args in as, well, individual args.
        push @args, @_;
        exec( $prog, @args ) or die "dcop can't exec: $!";
    }

    return $ret;
}

package main;

# see if knotes is running
my $dcop = new DCOP( target => 'knotes',
                     user => $ENV{LOGNAME},
                     control => 'KNotesIface' );

if ( $dcop->run()) {
    my $title;
    my $text;
    my $mode = "append";

    GetOptions( "id=s" => \$title,
                "title=s" => \$title,
                "text=s" => \$text,
                "dump" => sub { $mode = "dump" },
                "replace" => sub { $mode = "replace" },
                "delete" => sub { $mode = "delete" } ) or die;

    if ( !($title||"")) {
        $title = shift;
    }

    if ( @ARGV ) {
        $text = join( " ", @ARGV );
    } else {
        $text = "";
    }

    # see if it's a note we already know about
    my $notes = $dcop->run( "notes" );
    my @notes = split( /\n/, $notes ) if $notes;

    if ( !($title||"")) {
        for my $note ( @notes ) {
            my ( $id, $title ) = split( /->/, $note, 2 );
            print "$id\t$title\n";
        }
        exit;
    }

    my $noteid = "";
    for my $note ( @notes ) {
        if ( $note =~ /^$title->/ or $note =~ m@->$title$@ ) {
            ( $noteid ) = $note =~ /^(.+?)->/;
        }
    }

    if ( !$noteid ) {
        exit if $mode eq "delete"; # makes no sense
        $dcop->run( "newNote", $title, $text );
    } else {
        if ( $mode eq "delete" ) {
            $dcop->run( "killNote", $noteid );
            exit;
        }

        # is there text? if not, just show the note
        if ( !$text ) {
            if ( $mode eq "dump" ) {
                print "-" x 10 . "\n";
                print $dcop->run( "name", $noteid );
                print "\n";
                print "=" x 10 . "\n";
                print $dcop->run( "text", $noteid );
                print "\n";
                print "-" x 10 . "\n";
            } else {
                $dcop->run( "showNote",  $noteid );
            }
        } else {
            if ( $mode eq "append" ) {
                my $havetext = $dcop->run( "text", $noteid );

                # maybe we should be deleting something
                if ( substr( $text, 0, 1 ) eq "-" ) {
                    my $kill = ".?"  . substr( $text, 1 );
                    if ( $havetext =~ s/$kill//s ) {
                        $text = "";
                    }
                }

                if ( substr( $havetext, -1 ) ne "\n" and $text ) {
                    $havetext .= "\n";
                }

                $text = $havetext . $text;
            }
            $dcop->run( "setText", $noteid, $text );
        }
    }
}
