# milkbone - conversation window

package Milkbone::Convo;

use Milkbone;

our $VERSION = '1.0';

use Tk(Ev);
use base qw(Tk::Toplevel);
use strict;
use warnings;

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->withdraw();

	$self->title("$buddy - Conversation");
	$self->update;
	
	# WIDGET CREATION BEGIN

	$self->{menu} = $self->Menu;

	$self->{menu_file} = $self->{menu}->cascade(-label => "File", -tearoff => 0);
	$self->{menu_file}->command(-label => "Close", -command => [$self, "destroy"]);

	$self->configure(-menu => $self->{menu});

	$self->{frame} = $self->Frame(-borderwidth => 0)->pack(-expand => 1, -fill => 'both');

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

	$self->{top} = $self->{frame}->Scrolled("Browser", -background => 'white', 
		-height => 6, -font => "times 12", -scrollbars => 'oe', -wrap => 'word', -takefocus => 0)->
		pack(-side => 'top', -expand => 1, -fill => 'both', -padx => 5);
	$self->{bottom} = $self->{frame}->Scrolled("BrowseEdit",
		-height => 6, -font => "times 12", -scrollbars => 'oe', -wrap => 'word',
		-spacing1 => 0, -spacing2 => 0, -spacing3 => 0)->
		pack(-expand => 1, -fill => 'both', -padx => 5);
	$self->{typing} = $self->{frame}->Label->pack(-anchor => 'w');
	$self->{frame}->Button(-text => "Send", -command => [$self, "on_send"])->
		pack(-pady => 3, -side => 'right', -anchor => 'center');
	$self->{frame}->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("<Escape>", [$self, "destroy"]);	
	$self->{bottom}->bind("<KeyPress>", [$self, "on_key"]);	
	$self->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->{bottom}->configure(-background => 'white');
	$self->{me} = data("me");
	$self->{buddy} = $buddy;
	$self->{empty} = 1;
	$self->{last_typed} = time;
	$self->{typing_status} = 0;

	$self->update;
	$self->geometry("480x320");
	$self->deiconify;
	hook("tk_seticon", -wnd => $self);
	$self->OnDestroy([$self, "on_destroy"]);
	$self->{bottom}->focus;
	$self->{rep_id} = $self->repeat(1000, [$self, "update_status"]);
}

1;