#!/usr/bin/perl
use v5.10.0;
use strict;
use warnings;
use WebService::HabitRPG;
use Config::Tiny;
use Data::Dumper;

# PODNAME: hrpg

# ABSTRACT: hrpg - Command line interface to HabitRPG

our $VERSION = '0.04'; # VERSION


if (not @ARGV) {
    say q{
    Usage:

    hrpg status                  : Show current HP/XP/GP
    hrpg tasks                   : Show current tasks
    hrpg habit|daily|reward|todo : Show tasks of current type
    hrpg new                     : Create new task 'hrpg new' for help.
    hrpg [+-] task               : Increment/decrement a task or habit

    Debugging commands:
    
    hrpg dump                    : Dump entire user info
    hrpg dump tasks              : Dump task info
    };

    exit 1;
}

# TODO: Support XDG?
my $config_file = "$ENV{HOME}/.habitrpgrc";

my $config = Config::Tiny->read( $config_file );

unless ($config->{auth}{api_token}) {
    die "Cannot find user credentials in $config_file\n";
}

my @bonus_constructor_args;

if ($ENV{HRPG_API_BASE}) {
    @bonus_constructor_args = ( api_base => $ENV{HRPG_API_BASE} );
}

my $hrpg = WebService::HabitRPG->new(
    api_token => $config->{auth}{api_token},
    user_id   => $config->{auth}{user_id},
    @bonus_constructor_args,
);

my $cmd = shift @ARGV;

given ($cmd) {
    when ('dump')   { 

        my ($option) = @ARGV;

        if (not $option) {
            say Dumper $hrpg->user; 
        }
        elsif ($option eq 'tasks') {
            say Dumper $hrpg->tasks;
        }
        else {
            say "Did you mean `$0 dump tasks`?";
            exit 1;
        }
    }

    when ('status') {
        my $user = $hrpg->user;

        my $name =  $user->{profile}{name}
                 || $user->{auth}{facebook}{displayName}
                 || $user->{auth}{local}{username}
                 || 'adventurer';

        say "Hark, $name! (Lv $user->{stats}{lvl})";

        say "HP: $user->{stats}{hp} / $user->{stats}{maxHealth}";
        say "XP: $user->{stats}{exp} / $user->{stats}{toNextLevel}";

        # Pretty-printing of money
        my $raw_gp = sprintf("%.4f", $user->{stats}{gp});
        ($raw_gp =~ /^(?<gp>\d+)\.(?<sp>\d{2})(?<cp>\d{2})$/);

        printf "GP: %d | SP: %2d | CP: %2d\n",$+{gp}, $+{sp}, $+{cp};
    }

    when (/^(?<type>habit|todo|daily|reward)$/) {
        my $tasks = $hrpg->tasks($+{type});

        foreach my $task (@$tasks) {
            next if $task->{type} eq 'todo' and $task->{completed};
            say format_task($task);
        }
    }

    when ('tasks') {
        my $tasks = $hrpg->tasks();

        my $last_type = "";

        foreach my $task (@$tasks) {
            next if $task->{type} eq 'reward';
            next if $task->{type} eq 'todo' and $task->{completed};

            if ($task->{type} ne $last_type) {
                say "\n === \u$task->{type} ===\n";
            }
            say format_task($task);
            $last_type = $task->{type};
        }
    }

    when (/^[+-]$/) {
        my ($task_name) = @ARGV;
        die "Usage: $0 $_ task\n" if not $task_name;

        my $direction = $_ eq '+' ? 'up' : 'down';

        my @candidates = $hrpg->search_tasks($task_name);

        if (@candidates == 1) {
            my $task = $candidates[0];
            say "Updating $task->{text} ($task->{id})";

            my $return = $hrpg->updown($task->{id}, $direction);
            say Dumper $return;
        }
        elsif (@candidates == 0) {
            say "No task matching '$task_name' found";
        }
        else {
            say "Did you mean...";

            foreach my $task (@candidates) {
                say "* $task->{text} ($task->{id})";
            }
        }
    }

    when ('new') {
        my ($type, $direction, $text, $note, $value) = @ARGV;
        my ($up, $down) = (0, 0);

        # TODO: Support rewards (which have 'value')

        my $usage_text = qq{Usage: $0 new [habit|todo|daily] +- "name" ["note"]\n};

        unless ($type and $direction and $text  ) { die $usage_text; }
        if     ($type !~ /^(?:habit|todo|daily)/) { die $usage_text; }
        if     ($direction !~ /^[+-]+$/         ) { die $usage_text; }

        if ($direction =~ /\+/) { $up   = 1; }
        if ($direction =~ /\-/) { $down = 1; }

        $note //= "";

        my $result = $hrpg->new_task(
            type => $type,
            text => $text,
            note => $note,
            up   => $up,
            down => $down,
        );

        say Dumper $result;
    }

    default {
        say "\nSorry, I didn't understand what you were asking for!";
        say "Try $0 with no arguments for help.\n";
        exit 1;
    }
}

# TODO: Move these to the API module? Maybe?

# Formats todo/daily tasks with checkmarks. Everything else gets bullets.

sub format_task {
    my ($task) = @_;

    my $formatted = "";

    if ($task->{type} =~ /^(?:daily|todo)$/) {
        if ($task->{completed}) {
            $formatted .= '[X] ';
        }
        else {
            $formatted .= '[ ] ';
        }
    }
    elsif ($task->{type} eq 'habit') {
        $formatted .= ' ';
        $formatted .= $task->{up}   ? "+"  : " "  ;
        $formatted .= $task->{down} ? "- " : "  " ;
    }
    else {
        $formatted .= "  * ";
    }

    $formatted .= $task->{text};

    return $formatted;
}

__END__

=pod

=head1 NAME

hrpg - hrpg - Command line interface to HabitRPG

=head1 VERSION

version 0.04

=head1 SYNOPSIS

Usage:

    hrpg status                  : Show current HP/XP/GP
    hrpg tasks                   : Show current tasks
    hrpg habit|daily|reward|todo : Show tasks of current type
    hrpg new                     : Create new task 'hrpg new' for help.
    hrpg [+-] task               : Increment/decrement a task or habit

    Debugging commands:
    
    hrpg dump                    : Dump entire user info
    hrpg dump tasks              : Dump task info

=head1 DESCRIPTION

This is a command-line client for the L<HabitRPG|http://habitrpg.com/>
service.  Use C<hrpg> with no arguments for help.

When using C<hrpg + task> and C<hrpg - task> any unique shortening of the
task name can be used.

=head1 SETUP

=head2 Installation

If you have not already installed this software, the easiest way
is to use L<cpanm> and L<local::lib>. If you don't have them installed,
it's easy with:

    curl -L http://cpanmin.us/ | perl - --self-upgrade
    ~/perl5/bin/cpanm -L ~/perl5 App::local::lib::helper
    source ~/perl5/bin/localenv-bashrc

You might want to put that last line in your F<~/.bashrc> file.

You can then install C<hrpg> and related utilities with:

    cpanm hrpg

=head2 Configuration

Create a F<.habitrpgrc> file in your home directory. Place in it
the following lines:

    [auth]
    user_id   = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    api_token = xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Replace the long strings of 'x's with the values you obtain by
going to I<Settings -> API> in the HabitRPG web interface.

=head1 ENVIRONMENT

If the C<HRPG_API_BASE> environment variable is set, it will be used as
the API base URL. This may be useful in testing, or when working with
other servers.

=head1 BUGS

I'm sure there are plenty! Please view and/or record them at
L<https://github.com/pfenwick/WebService-HabitRPG/issues> .

=head1 SEE ALSO

L<WebService::HabitRPG>

=head1 AUTHOR

Paul Fenwick <pjf@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2013 by Paul Fenwick.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut
