#
#===============================================================================
#
#  DESCRIPTION: plugin for LIMS::Local::IssueTracker
#  requires two trello boards. 'RFCs' and 'Test' both containing 'Backlog' and
#  'Completed' lists
#
# WWW::Trello::Lite v1.00 requires force-install - 2/4 tests fail because:
# Role::REST::Client returns '1' for failure not '' (WWW-Trello-Lite.t test #3),
# and response->content string 'invalid key' does not have a new-line (test #4)
#===============================================================================
package LIMS::Local::IssueTracker::Plugin::Trello;

use Modern::Perl;
use utf8;
use WWW::Trello::Lite;

use Moose::Role;
use Data::Dumper;
use Data::Printer;
use JSON;

has 'trello' => (
    is      => 'ro',
    isa     => 'WWW::Trello::Lite',
    lazy    => '1',
    builder => '_build_trello'
);

sub _build_trello {
    my $self  = shift;
    my $key   = $self->config->{key};
    my $token = $self->config->{token};

    return WWW::Trello::Lite->new( key => $key, token => $token );
}

sub check_config {
    my $self   = shift;
    my $config = $self->config;

    # mandatory config fields
    my @mandatory_issue_lists = qw/new complete rejected/;

    if (
        ( grep    { not exists $config->{$_} } qw(key token) )
        or ( grep { not exists $config->{board}->{lists}->{$_}->{name} }
            @mandatory_issue_lists )
        or ( grep { not exists $config->{board}->{lists}->{$_}->{id} }
            @mandatory_issue_lists )
      )
    {
        return 0;
    }
    else {
        return 1;
    }
}

sub create_rfc {
    my $self           = shift;
    my $args           = shift;
    my $trello         = $self->trello;
    my $new_cards_list = $self->config->{board}->{lists}->{new}->{id};
    my $res            = $trello->post(
        "cards",
        {
            idList => $new_cards_list,
            name   => $args->{name},
            desc   => $args->{desc}
        }
    );
    die "Trello error posting new card: $!" if $res->code != 200;

    my $json      = JSON->new->allow_nonref;
    my $json_data = $json->decode( $res->{response}->{_content} );

    my $card_id = $json_data->{id};
    my $colour  = $self->config->{colours}->{ $args->{reason} };
    $res = $trello->post( "cards/$card_id/labels", { color => $colour } );
    die "Trello error adding label to card: $!" if $res->code != 200;

    return $json_data->{id};

}

sub check_status {
    my $self   = shift;
    my $id     = shift;
    my $trello = $self->trello;
    my $res    = $trello->get("cards/$id");
    die "Trello error: can't get card $id :$!" if $res->code != 200;

    my $json      = JSON->new->allow_nonref;
    my $json_data = $json->decode( $res->{response}->{_content} );
    my $list_id   = $json_data->{idList};
    $res = $trello->get("lists/$list_id/name");
    die "Trello error: can't get list name from id $list_id :$!"
      if $res->code != 200;

    my $json_listdata = $json->decode( $res->{response}->{_content} );

    return $json_listdata->{_value};

}

# boolean check if card is in list
sub is_status {
    my $self      = shift;
    my $list_name = shift;
    my $id        = shift;
    my $list      = $self->config->{board}->{lists}->{$list_name}->{name};
    my $status    = $self->check_status($id);
    if ( $status eq $list ) {
        return 1;
    }
    else { return 0; }
}

# takes ArrayRef of ids and returns a ArrayRef of ids in Completed list
sub check_complete {
    my $self     = shift;
    my $ids      = shift;
    my @complete = grep { $self->is_status( 'complete', $_ ) } @$ids;
    return \@complete;
}

# takes ArrayRef of ids and returns a ArrayRef of ids in Rejected list
sub check_rejected {
    my $self     = shift;
    my $ids      = shift;
    my @rejected = grep { $self->is_status( 'rejected', $_ ) } @$ids;
    return \@rejected;
}

sub move_card {
    my $self        = shift;
    my $trello      = $self->trello;
    my $card_id     = shift;
    my $destination = shift || die "requires destination: $!";
    my $list_id     = $self->config->{board}->{lists}->{$destination}->{id};
    my $res         = $trello->put( "cards/$card_id", { idList => $list_id } );
    die "Trello error: can't move card $card_id :$!"
      if $res->code != 200;
}
1;

__END__

---
plugin: Trello
user: hilis1
key: 9b06292374140f6a3d5286c4c1a793b8
token: bcf4986d275f9ea3dd8acf0e98a752f2a8b79d9bc53904192590399aa973e03c
colours:
  new feature: green
  modification: yellow
  fix error: red
  change menu: blue
board:
  live:
    name: RFCs
    id: 59f363276bc164d702084859
    lists:
      new:
        name: Backlog
        id: 59f36340b83960f54a5f0ed3
      complete:
        name: Completed
        id: 59f3636231f832f37b38a418
      rejected:
        name: Rejected
        id: 59f363662a7a191c28e2027c
  test:
    id: 59f3611fae00c3065645e689
    lists:
      new:
        name: Backlog
        id: 59f9ba943b5d56ce4b512ad5
      complete:
        name: Completed
        id: 59f9bd8963d7817d02661832
      rejected:
        name: Rejected
        id: 59f9d831d9438d79b78d82aa

#Its a pain to get all the ids for lists and boards etc.
#to get ids from trello api use REPL and inspect the response
#See: https://developers.trello.com/reference/
#
#$trello->get("members/garry222/boards");
#my $res =$trello->get("lists/59f36340b83960f54a5f0ed3/cards");
#$trello->get("lists/59f36340b83960f54a5f0ed3/cards");
#48> my $res =$trello->post("cards", {idList => '59f9ba943b5d56ce4b512ad', name =>"xxxxxxxxx" , desc =>"1 2 3 4"});
#53> $trello->get("cards/59f9c79b61a559aba10d4dd5")
#etc...
