use warnings;
use strict;

=head1 NAME

BarnOwl::Module::Pushbullet

=head1 DESCRIPTION

Push some incoming zephyrs to Pushbullet

=cut

package BarnOwl::Module::Pushbullet;

our $VERSION = 0.1;

use JSON;
use AnyEvent::HTTP;
use MIME::Base64;

use BarnOwl;
use BarnOwl::Hooks;

my $conffile = BarnOwl::get_config_dir() . "/pushbullet";
my $authToken;
my @pushMap;
my %headers = (
    "content-type" => "application/json; charset=utf-8",
    );

sub queue_admin_msg {
    my $msg = shift;
    BarnOwl::admin_message("Pushbullet", $msg);
}

sub fail {
    my $msg = shift;
    $authToken = '';
    @pushMap = ();
    BarnOwl::admin_message('Pushbullet Error', $msg);
    die("Pushbullet Error: $msg\n");
}

sub read_config {
    my $fh = shift;

    my $raw_cfg = do {local $/; <$fh>};
    my $cfg;
    close($fh);
    eval {
        $cfg = from_json($raw_cfg);
    };

    if($@) {
        fail("Unable to parse $conffile: $@");
    }

    # Perform some sanity checking on the configuration.
    if(! exists $cfg->{authToken}) {
        fail("Account has no authToken set.");
    }
    $authToken = $cfg->{authToken};

    if(! exists $cfg->{pushMap}) {
        fail("Account has no pushMap configured.");
    }

    $headers{Authorization} = "Basic " . MIME::Base64::encode($authToken . ':', '');
    @pushMap = ();
    for my $pcfg (@{$cfg->{pushMap}}) {
        push @pushMap, $pcfg if $pcfg->{filter};
    }
}

if (open(my $fh, "<", "$conffile")) {
    read_config($fh);
    close($fh);
}

sub write_config {
    my %cfg = (
        authToken => $authToken,
        pushMap => \@pushMap
        );

    if (open(my $fh, ">", "$conffile")) {
        print $fh to_json(\%cfg, { pretty => 1 });
        close($fh);
    } else {
        queue_admin_msg("Unable to save settings");
    }

}

my $pushUrl = "https://api.pushbullet.com/v2/pushes";

# We may eventually want to do something when we fail to push a message.
sub cb {};

sub pushGeneric {
    my $m = shift;
    my $deviceIden = shift;
    my %payload = (
        type => "note",
        title => $m->{type} . " from " . $m->pretty_sender,
        body => $m->body
        );

    $payload{'device_iden'} = $deviceIden if $deviceIden;

    http_post($pushUrl, to_json(\%payload),
              headers => \%headers,
              \&cb);

}

sub pushZephyr {
    my $m = shift;
    my $deviceIden = shift;
    my %payload = (
        type => "note",
        );
    $payload{device_iden} = $deviceIden if $deviceIden;

    if ($m->is_personal) {
        $payload{title} = "zephyr from " . $m->pretty_sender;
        $payload{body} = $m->body;
    } else {
        $payload{title} = lc($m->class) . ' / ' . lc($m->instance);
        $payload{body} = $m->pretty_sender . " says:\n" . $m->body;
    }
    http_post($pushUrl, to_json(\%payload),
              headers => \%headers,
              \&cb);
}

sub handle_message {
    my $m = shift;
    my $quiet = 1;
    for my $p (@pushMap) {
        next if (!BarnOwl::message_matches_filter($m, $p->{filter}, $quiet));
        if ($m->is_zephyr) {
            pushZephyr($m, $p->{deviceIden});
        } else {
            pushGeneric($m, $p->{deviceIden});
        }
    }
}

sub setup {
    queue_admin_msg("please visit: http://asedeno.mit.edu/oauth/pushbullet/setup.html");
}



eval {
    $BarnOwl::Hooks::receiveMessage->add("BarnOwl::Module::Pushbullet::handle_message");
};
if($@) {
    $BarnOwl::Hooks::receiveMessage->add(\&handle_message);
}

1;
