# milkbone - conversation window

package Milkbone::Convo;

use Milkbone;

our $VERSION = '1.0';

use Tk qw(Ev);
use Tk::widgets qw(Frame);
use base qw(Tk::Frame);
use strict;
use warnings;
use Tk::BrowseEdit;

Construct Tk::Widget 'MBConvo';

sub ClassInit
{
    my ($class, $mw) = @_;
    $class->SUPER::ClassInit($mw);
}

sub Populate
{
    my ($self, $args) = @_;
    $self->SUPER::Populate($args);

    $self->ConfigSpecs('DEFAULT' => ['SELF']);
}

sub on_send
{
    my $self = shift;
    my $msg = $self->{bottom}->to_html('0.0', 'end');

    $msg =~ s/\n*$//;
    $msg =~ s/\r\n?//g;
    $msg =~ s/\n/<br>/g;

    return if($msg eq "");

    $msg =~ s/&amp;/&/g;
    $msg =~ s/&quot;/\"/g;
    $msg =~ s/%ignore%//gi;
    $self->{bottom}->delete('0.0', 'end');
    # $self->{bottom}->ResetUndo;

    hook("protocol_send_im", -dest => $self->{buddy}, -msg => $msg, -away => 0);
    $self->{typing_status} = 0;
    $self->{text_entered} = 0;
    $self->{typing_empty} = 0;
    hook("protocol_set_typing_status", -user => $self->{buddy}, -status => 0);
}

sub msg_sent
{
    my ($self, $msg, $away) = @_;
    my $nl = $self->{empty} ? "" : "\n";

    $self->{top}->insert('end', $nl . data("me"), 'self');
    $self->{top}->insert('end', $self->make_timestamp, 'self_stamp');
    $self->{top}->insert('end', ": ", 'self');
    $self->{top}->insertHTML('end',  $msg);
    $self->{top}->yview($self->{top}->index('end'));
    $self->{empty} = 0;
}

sub on_receive
{
    my ($self) = @_;
    my $nl = $self->{empty} ? "" : "\n";

    $self->{top}->insert('end', "${nl}$ARGS{-user}", 'buddy');
    $self->{top}->insert('end', $self->make_timestamp, 'buddy_stamp');
    $self->{top}->insert('end', ": ", 'buddy');
    $self->{top}->insertHTML('end', "$ARGS{-msg}");
    $self->{top}->yview($self->{top}->index('end'));
    $self->{empty} = 0;
    $self->typing_status(0);
}

sub on_destroy
{
    my ($self) = @_;
    hook("remove_convo", -user => shift->{buddy});
    $self->{rep_id}->cancel;
    hook("protocol_set_typing_status", -user => $self->{buddy}, -status => 0);
}

sub on_prof
{
    hook("get_profile", -user => shift->{buddy});
}

sub on_buddy_in
{
    my ($self) = @_;

    $self->{top}->insert('end', "\n" . $self->{buddy} . " has signed in.", "buddy") if $self->{out};
    $self->{out} = 0 if(defined($self->{out}) and $self->{out} == 1);
    $self->{top}->yview($self->{top}->index('end'));
}

sub on_buddy_out
{
    my ($self) = @_;

    $self->{top}->insert('end', "\n" . $self->{buddy} . " has signed out.", "buddy");
    $self->{out} = 1;
    $self->{top}->yview($self->{top}->index('end'));
}

sub make_timestamp
{
    my ($self) = @_;

    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;

    $sec = sprintf("%02d", $sec);
    my $pm = ($hour > 12) ? 'PM' : 'AM';
    $hour = $hour % 12;
    $year += 1900;
    $year %= 100;

    return " (" . $mon . "/" . $mday . "/" . $year . " " . $hour . ":" . $min . ":" . $sec . " " . $pm . ") ";
}

sub toggle_stamps
{
    my ($self) = @_;
    $self->{hide_stamps} = !$self->{hide_stamps};

    $self->{top}->tagConfigure('self_stamp', -elide => $self->{hide_stamps});
    $self->{top}->tagConfigure('buddy_stamp', -elide => $self->{hide_stamps});
}

sub typing_status
{
    my ($self, $status) = @_;

    my @msgs = ("", $self->{buddy} . " has typed text.", $self->{buddy} . " is typing...");

    $self->{typing}->configure(-text => $msgs[$status]);
}

sub on_key
{
    my ($self) = @_;

    if($self->{typing_status} == 0)
    {
        hook("protocol_set_typing_status", -user => $self->{buddy}, -status => 2);
        $self->{typing_status} = 2;
    }
    $self->{last_typed} = time;
}

sub update_status
{
    my ($self) = @_;

    if($self->{bottom}->get('0.0', 'end') =~ /^\s*$/ && $self->{typing_status})
    {
        hook("protocol_set_typing_status", -user => $self->{buddy}, -status => 0);
        $self->{typing_status} = 0;
        return;
    }

    if((time - $self->{last_typed}) >= 5 && $self->{typing_status} == 2)
    {
        hook("protocol_set_typing_status", -user => $self->{buddy}, -status => 1);
        $self->{typing_status} = 1;
    }
}

sub init
{
    my ($self, $mw, $buddy) = @_;

    $self->update;
    
    # WIDGET CREATION BEGIN

    $self->{off} = 0;
    $self->{hide_stamps} = 1;

    $self->{top} = $self->Scrolled("Browser", 
                                   -height => 6, -font => "{adobe arial} 12", -scrollbars => 'oe', -wrap => 'word', -takefocus => 0)->
                                       pack(-side => 'top', -expand => 1, -fill => 'both', -padx => 5);
    $self->{bottom} = $self->Scrolled("BrowseEdit",
                                      -height => 6, -font => "{adobe arial} 12", -scrollbars => 'oe', -wrap => 'word',
                                      -spacing1 => 0, -spacing2 => 0, -spacing3 => 0)->
                                          pack(-expand => 1, -fill => 'both', -padx => 5);
    $self->{top}->configure(-background => 'white');
    $self->{typing} = $self->Label->pack(-anchor => 'w');
    $self->Button(-text => "Send", -command => [$self, "on_send"])->
        pack(-pady => 3, -side => 'right', -anchor => 'center');
    $self->Button(-text => "Get Profile", -command => [$self, "on_prof"])->
        pack(-pady => 3, -side => 'left', -anchor => 'center');

    # WIDGET CREATION END

    $self->{top}->tagConfigure('self', -foreground => 'red', -font => 'times 12 bold');
    $self->{top}->tagConfigure('buddy', -foreground => 'blue', -font => 'times 12 bold');
    $self->{top}->tagConfigure('self_stamp', -foreground => 'red', -elide => 1, -font => 'times 9 bold');
    $self->{top}->tagConfigure('buddy_stamp', -foreground => 'blue', -elide => 1, -font => 'times 9 bold');

    $self->{bottom}->bind("<Return>", [$self, "on_send"]);
    $self->{bottom}->bind("<Control-Return>", [sub { $self->{bottom}->insert('insert', "\r\n")}, $self]);
    $self->{bottom}->bind("<KeyPress>", [$self, "on_key"]);
    $self->bind("<F2>", [$self, "toggle_stamps"]);
    $self->{bottom}->bind("<F2>", [$self, "toggle_stamps"]);
    $self->{top}->bind("<F2>", [$self, "toggle_stamps"]);

    hook("tk_bindwheel", -window => $self->{bottom});
    hook("tk_bindwheel", -window => $self->{top});

    # $self->bind('<Configure>', [sub {
    # my ($width, $height) = @_;
    # set_option('ConvoHeight', $height);
    # set_option('ConvoWidth', $width);
    # }, Ev('w'), Ev('h')]);

    $self->{me} = data("me");
    $self->{buddy} = $buddy;
    $self->{empty} = 1;
    $self->{last_typed} = time;
    $self->{typing_status} = 0;

    $self->{bottom}->focus;
    $self->{rep_id} = $self->repeat(1000, [$self, "update_status"]);
}

1;