/usr/local/CPAN/RT-Client-Console/RT/Client/Console/Session/Ticket/Attachments.pm


package RT::Client::Console::Session::Ticket::Attachments;

use strict;
use warnings;

use parent qw(RT::Client::Console::Session);

use Curses::Widgets; # for textwrap
use Curses::Widgets::ListBox;
use Curses::Widgets::TextMemo;
use Error qw(:try);
use Params::Validate qw(:all);
use POE;
use Memoize;
use RT::Client::REST::User;
use relative -to => "RT::Client::Console", 
        -aliased => qw(Connection Session Session::Ticket Session::Progress);


# class method


### THIS MODULE IS DEPRECATED, BUT COULD BE USED AS A PLUGIN ###

# attachments session creation
sub create {
    my ($class, $ticket_id) = @_;
    $class->SUPER::create(
    "ticket_attachments_$ticket_id",
    inline_states => {
        init => sub {
            my ($kernel, $heap) = @_[ KERNEL, HEAP ];
            $heap->{pos_x } = 0;
            $heap->{pos_y } = 1 + 7 + 6;  # tabs-bar + headers + custhdrs
		},
	    window_resize => sub {
            my ($kernel, $heap, $old_screen_h, $old_screen_w) = @_[ KERNEL, HEAP, ARG0, ARG1 ];
            $heap->{width} = $heap->{screen_w} * 2 / 3 - 2;  # - border;
            $heap->{height} = $heap->{screen_h} - $heap->{pos_y} - 2 - 2;
        },
        available_keys => sub {
            return (['<KEY_NPAGE>', 'next attachment',  'next_attachment'],
                    ['<KEY_PPAGE>', 'prev. attachment', 'prev_attachment'],
                    ['<KEY_UP>',    'scroll up',        'scroll_up'      ],
                    ['<KEY_DOWN>',  'scroll down',      'scroll_down'    ],
                    ['b',           'page up',          'page_up'        ],
                    [' ',           'page down',        'page_down'      ],
                   );
        },

        next_attachment => sub {
            my ( $kernel, $heap) = @_[ KERNEL, HEAP ];
            $heap->{current}++;
            $heap->{current} > $heap->{total} - 1
              and $heap->{current} = $heap->{total} - 1;
            $heap->{positions}[$heap->{current}]->{current} = 0;
        },

        prev_attachment => sub {
            my ( $kernel, $heap) = @_[ KERNEL, HEAP ];
            $heap->{current}--;
            $heap->{current} < 0
              and $heap->{current} = 0;
            $heap->{positions}[$heap->{current}]->{current} = 0;
        },

        scroll_down => sub {
             my ($kernel, $heap, $offset) = @_[ KERNEL, HEAP, ARG0 ];
            $offset ||= 1;
             my $idx = $heap->{current};
            my $positions = $heap->{positions}[$idx];
            defined $positions or return -1;
            if ($positions->{current} >= @{$positions->{array}} - $offset) {
                if ($heap->{current} < $heap->{total} - 1 ) {
                    $heap->{current}++;
                    if (defined $heap->{positions}[$idx + 1]) {
                        $heap->{positions}[$idx + 1]->{current} = 0;
                    }
                    $kernel->call("ticket_attachments_$ticket_id", 'draw');
                }
                return -1;
            }
            $positions->{current} += $offset;
            $kernel->call("ticket_attachments_$ticket_id", 'draw');
            return -1;
        },

        scroll_up => sub {
             my ($kernel, $heap, $offset) = @_[ KERNEL, HEAP, ARG0 ];
             $offset ||= 1;
             my $idx = $heap->{current};
            my $positions = $heap->{positions}[$idx];
            defined $positions or return -1;
            if ($positions->{current} <= ($offset-1)) {
                if ($heap->{current} > 0) {
                    $heap->{current}--;
                    if (defined $heap->{positions}[$idx - 1]) {
                        $heap->{positions}[$idx - 1]->{current} =
                          @{$heap->{positions}[$idx - 1]->{array}} - 1;
                    }
                    $kernel->call("ticket_attachments_$ticket_id", 'draw');
                }
                return -1;
            }
            $positions->{current} -= $offset;
             $kernel->call("ticket_attachments_$ticket_id", 'draw');
            return -1;
        },

        page_down => sub {
             my ($kernel, $heap) = @_[ KERNEL, HEAP ];
             my $offset = int($heap->{height} / 2);
            $kernel->call("ticket_attachments_$ticket_id", 'scroll_down', $offset);
        },

        page_up => sub {
             my ($kernel, $heap) = @_[ KERNEL, HEAP ];
             my $offset = int($heap->{height} / 2);
            $kernel->call("ticket_attachments_$ticket_id", 'scroll_up', $offset);
        },

        draw => sub {
            my ($kernel, $heap) = @_[ KERNEL, HEAP ];
            my $label;

            if (!defined($heap->{attachments})) {
                $class->_generate_job($kernel, $heap, $ticket_id);
            }
            defined($heap->{attachments}) or return;
            my $total = $heap->{total};
            $total > 0 or return;
            $heap->{current} ||= 0;

            my $idx = $heap->{current};

            my $attachment = $heap->{attachments}->[$idx];

            my $text = '...loading...';
            my $user_details = '';

            if (defined $attachment) {
                try {
                    my $user_id = $attachment->creator_id();
                    my $rt_handler = Connection->get_cnx_data()->{handler};

                    my ($user, $user_name, $user_email, $user_real_name, $user_gecos, $user_comments)
                      = _get_user_details( rt  => $rt_handler,
                                           id  => $user_id,
                                         );
                    $user_details = "By: $user_real_name ($user_name) <$user_email>";
                    
                } catch Exception::Class::Base with {
                    my $e = shift;
                    warn ref($e), ": ", $e->message || $e->description, "\n";
                };
                
                $text = $class->as_text($heap, $attachment, $idx, $heap->{width}, $ticket_id);
            }
            my $title = '[ Attachment ' . ($idx + 1) . " / $total - $user_details ]";
            $title =~ s/\s+/ /g;

            my ($textstart, $cursorpos) = (0, 0);
            my $positions = $heap->{positions}[$idx];
            if (defined $positions) {
                ($textstart, $cursorpos) = @{$positions->{array}[$positions->{current}]};
            }
            print STDERR "+++ SCROLL : text start : $textstart\n";
            print STDERR "+++ CURSOR : $cursorpos\n";

             my $widget = Curses::Widgets::TextMemo->new(
                     {
                      X           => $heap->{'pos_x'},
                      Y           => $heap->{'pos_y'},
                      COLUMNS     => $heap->{width},
                      LINES       => $heap->{height},
                      MAXLENGTH   => undef,
                      FOREGROUND  => 'white',
                      BACKGROUND  => 'black',
                      VALUE       => $text,
                      BORDERCOL   => 'red',
                      BORDER      => 1,
                      CAPTION     => $title,
                      CAPTIONCOL  => 'yellow',
                      READONLY    => 1,
                     TEXTSTART   => $textstart,
                     CURSORPOS   => $cursorpos,
                    }
             );
            $widget->draw($class->get_curses_handler());

            # draw keys
            my @keys = map {
                my $n = $_->[0];
                $n =~ s/<KEY_(.*)>/$1/;
                [ lc($n), @{$_}[1,2] ];
            } $kernel->call("ticket_attachments_$ticket_id" => 'available_keys');            
            $class->draw_keys_label( Y => $heap->{'pos_y'} + $heap->{height} + 1 ,
                                     X => $heap->{'pos_x'} + 5,
                                     COLUMNS => $heap->{width} - 2,
                                     VALUE => \@keys,
                                     BACKGROUND  => 'black'
                                   );
        },
    },
    heap => { 'pos_x' => 0,
              'pos_y' => 0,
              'width' => 0,
              'height' => 0,
              positions => [],
              text => [],
            },
    );
}


memoize('_get_user_details');

sub _get_user_details {
    my (%args) = @_;
    my $user = RT::Client::REST::User->new( %args )->retrieve;
    my $user_name = $user->name();
    my $user_email = $user->email_address();
    my $user_real_name = $user->real_name();
    my $user_gecos = $user->gecos();
    my $user_comments = $user->comments();
    return ($user, $user_name, $user_email, $user_real_name, $user_gecos, $user_comments);
}

sub as_text {
    my ($class, $heap, $attachment, $idx, $width, $ticket_id) = @_;
    defined $heap->{text}[$idx] and return $heap->{text}[$idx];
    my $s = 'content :(' . $attachment->content_type() . ')' . "\n"
          . 'subject :{' . $attachment->subject() . '}' . "\n"
          . 'filename:{' . $attachment->file_name() . '}' . "\n"
          . 'created :{' . $attachment->created() . '}' . "\n"
          . 'transac :{' . $attachment->transaction_id() . '}' . "\n"
          . 'message :{' . $attachment->message_id() . '}';
    if (defined $attachment->transaction_id()) {
        my $id = $attachment->transaction_id();
        $s .= "\n--- transaction $id ----\n";
        my $rt_handler = Connection->get_cnx_data()->{handler};
        my $transaction = $rt_handler->get_transaction(parent_id => $ticket_id,
                                                       id => $id);

#        my $ticket = Ticket->get_ticket_from_id($ticket_id);
#RT::Client::REST::Ticket
#        my $transaction = RT::Client::REST($ticket,parent_id => $ticket_id,
#                                                              id => $id);
#        my $transaction = $ticket->get_transaction(parent_id => $ticket_id,
#                                                   id => $id);
        use Data::Dumper;
        $s .= Dumper($transaction);
        $s .= "\n------------\n";
    }
    my $text;
    if ($attachment->content_type eq 'text/plain') {
        $text = $s . "\n\n" . $attachment->content();
    } elsif ($attachment->content_type eq 'multipart/mixed') {
        $text = $s . "\n\n[" . $attachment->content() . "]\n";
    } else {
        $text = $s;
    }
    $heap->{text}[$idx] = $text;
    my @lines = textwrap($text, $width - 1);
    my $i = 0;
    my $l = 0;
    $heap->{positions}[$idx] = 
      {
       current => 0,
       array => [
                 [ 0, 0 ],
                 map { [ ++$i, $l += length ]; } @lines,
                ],
      };
    return $text;
}

sub _generate_job {
    my ($class, $kernel, $heap, $ticket_id) = @_;
    $heap->{attachments} = [];

    my @ids;
    my $idx = 0;
    my $rt_handler = Connection->get_cnx_data()->{handler};
    my $iterator;
    Progress->add_progress(
            steps_nb => sub { $heap->{total} },
            caption => sub { 'attachments' },
            initially => sub {
                my $ticket = Ticket->get_current_ticket();
                my $attachments_obj = $ticket->attachments();
                my $count = $attachments_obj->count();
                $heap->{total} = $count;
                $iterator = $attachments_obj->get_iterator();
            },
            code => sub {
                my $attachment = $iterator->();
                defined $attachment or return;
                push @{$heap->{attachments}}, $attachment;
                $idx++ or $kernel->post('key_handler', 'draw_all');
                return 1;
            },
            finally => sub { },
    );
}


1;