##############################################################################
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
#  Jabber
#  Copyright (C) 1998-1999 The Jabber Team http://jabber.org/
#
##############################################################################

package Tk::Roster;

use vars qw($VERSION);
$VERSION = '0.1';

use Tk;
require Tk::Frame;

use Carp;
use strict;
use base qw(Tk::Frame Jarl::Roster);
Construct Tk::Widget 'Roster';


##############################################################################
#
# Populate - Create the Tk widget
#
##############################################################################
sub Populate {
  my ($self, $args) = @_;
  my %args = %{$args};

  $self->{varsOnlineOnly} = 0;

  $self->{varsRosterBackground} =
    $self->ParseArg($args,"-rosterbackground","white");
  $self->{varsGroupBackground} =
    $self->ParseArg($args,"-groupbackground","grey65");
  $self->{varsGroupForeground} =
    $self->ParseArg($args,"-groupforeground","white");
  $self->{varsJIDBackground} =
    $self->ParseArg($args,"-jidbackground","grey75");
  $self->{varsJIDForeground} =
    $self->ParseArg($args,"-jidforeground","black");
  $self->{varsSelectBackground} =
    $self->ParseArg($args,"-selectbackground","lightblue");
  $self->{varsResourceBackground} =
    $self->ParseArg($args,"-resourcebackground","grey85");
  $self->{varsResourceForeground} =
    $self->ParseArg($args,"-resourceforeground","black");
  $self->{varsBalloon} =
    $self->ParseArg($args,"-balloon",undef);
  $self->{varsFont} =
    $self->ParseArg($args,"-font","");
  $self->{varsJIDLeftCommand} =
    $self->ParseArg($args,"-jidleftcommand","");
  $self->{varsJIDRightCommand} =
    $self->ParseArg($args,"-jidrightcommand","");
  $self->{varsUpdateMode} =
    $self->ParseArg($args,"-updatemode","roster");
  $self->{varsWidth} =
    $self->ParseArg($args,"-width",200);

  $self->{frame} =
    $self->
      Frame(%{$args}
	   )->pack(-side=>'top',
		   -padx=>0,
		   -pady=>0,
		   -fill=>'both',
		   -expand=>1);

  my $scrolled =
    $self->{frame}->
      Scrolled("Canvas",
	       -scrollbars=>"osoe",
	       -height=>10,
	       -width=>$self->{varsWidth},
	       -borderwidth=>0,
	       -relief=>"flat",
	       -background=>$self->{varsRosterBackground},
	       -takefocus=>0,
	       -highlightthickness=>0
	      )->pack(-side=>'top',
		      -fill=>'both',
		      -expand=>1,
		      -padx=>0,
		      -pady=>0);

  $self->{canvas} = $scrolled->Subwidget("canvas");
  $scrolled->Subwidget("yscrollbar")->configure(-width=>10,
						-borderwidth=>1,
						-relief=>"flat",
						-takefocus=>0,
						-highlightthickness=>0
					       );
  $scrolled->Subwidget("xscrollbar")->configure(-width=>10,
						-borderwidth=>1,
						-relief=>"flat",
						-takefocus=>0,
						-highlightthickness=>0
					       );

  $self->{balloons} = {} if defined($self->{varsBalloon});
}


##############################################################################
#
# ParseArg - Helper function to extract the specified argument from the
#            function call.
#
##############################################################################
sub ParseArg {
  my $self = shift;
  my ($args,$arg,$default) = @_;
  return (exists($args->{$arg}) ? delete($args->{$arg}) : $default);
}


##############################################################################
#
# Draw - Draw the roster.
#
##############################################################################
sub Draw {
  my $self = shift;

  $self->{canvas}->createText(-1000,-1000,
			    -text=>"TestString",
                            (
                             (ref($self->{varsFont}) eq "Tk::Font") ?
                             (-font=>$self->{varsFont}) :
                             (
                               ($self->{varsFont} ne "") ?
                               (-font=>$self->{varsFont}) :
                               ()
                             )
                            ),
	                    -tags=>[ "rostertest" ]);

  my ($x1,$y1,$x2,$y2) = $self->{canvas}->bbox("rostertest");

  $self->{varsItem}->{Height} = $y2 - $y1 + 4;
  $self->{varsItem}->{Height} = 16 if ($self->{varsItem}->{Height} < 16);

  $self->{canvas}->delete("all");

  $self->{varsY} = 0;

  foreach my $group ($self->GetGroups()) {

    $self->DrawItem($self->CreateTag($group),"group",$group,0)
      unless (($self->{varsOnlineOnly} == 1) &&
              ($self->ActiveGroup($group) == 0));

    if ($self->{groups}->{$group}->{'__roster__:status'} == 1) {
      foreach my $jid (sort {uc($self->{jids}->{$a}->{name}) cmp uc($self->{jids}->{$b}->{name})} keys(%{$self->{groups}->{$group}})) {
	next if ($jid eq '__roster__:status');
	next if (($self->{varsOnlineOnly} == 1) && !defined($self->Resource($jid)));
	$self->DrawItem($self->CreateTag($group,$jid),"jid",$self->{jids}->{$jid}->{name},1);
	if ($self->{groups}->{$group}->{$jid} == 1) {
	  foreach my $resource (sort {$self->{resources}->{$jid}->{$b}->{priority} <=> $self->{resources}->{$jid}->{$a}->{priority}} keys(%{$self->{resources}->{$jid}})) {
	    $self->DrawItem($self->CreateTag($group,$jid,$resource),"resource",$resource,2);
	  }
	}
      }
    }
  }

  foreach my $jid (sort {uc($self->{jids}->{$a}->{name}) cmp uc($self->{jids}->{$b}->{name})} keys(%{$self->{groups}->{'__roster__:none'}})) {
    next if ($jid eq '__roster__:status');
    next if (($self->{varsOnlineOnly} == 1) && !defined($self->Resource($jid)));
    $self->DrawItem($self->CreateTag('__roster__:none',$jid),"jid",$self->{jids}->{$jid}->{name},0);
    if ($self->{groups}->{'__roster__:none'}->{$jid} == 1) {
      foreach my $resource (sort {$self->{jids}->{$jid}->{resources}->{$b}->{priority} <=> $self->{resources}->{$jid}->{$a}->{priority}} keys(%{$self->{resources}->{$jid}})) {
	$self->DrawItem($self->CreateTag('__roster__:none',$jid,$resource),"resource",$resource,1);
      }
    }
  }

  (undef,undef,undef,$y2) = $self->{canvas}->bbox("all");

  (undef,undef,$x2,undef) = $self->{canvas}->bbox("text");

  $x2 = 10 unless ($x2 > 10);
  $y2 = 10 unless ($y2 > 10);

  $self->{canvas}->
    configure(-scrollregion=>
	      [ 0,
		0,
		($x2+2),
		$y2
	      ]);

  $self->{varsBalloon}->
    attach($self->{canvas},
	   -balloonposition => 'mouse',
	   -msg=>{ %{$self->{balloons}} },
	  )
      if defined($self->{varsBalloon});

  if (defined($self->{varsSelectedTag}) &&
      ($self->{canvas}->gettags($self->{varsSelectedTag}) ne "")) {
    $self->{canvas}->itemconfigure($self->{varsSelectedTag},
				 -fill=>$self->{varsSelectBackground});
  } else {
    $self->{varsSelectedJID} = undef;
    $self->{varsSelectedTag} = undef;
  }
}


##############################################################################
#
# DrawItem - Draw a single item entry.
#
##############################################################################
sub DrawItem {
  my $self = shift;
  my ($tag,$type,$text,$indentLevel) = @_;

  my %types;
  $types{group}->{back} = $self->{varsGroupBackground};
  $types{group}->{fore} = $self->{varsGroupForeground};
  $types{jid}->{back} = $self->{varsJIDBackground};
  $types{jid}->{fore} = $self->{varsJIDForeground};
  $types{resource}->{back} = $self->{varsResourceBackground};
  $types{resource}->{fore} = $self->{varsResourceForeground};

  my ($group,$jid,$resource);

  foreach my $splitTag (split(':::',$tag)) {
    ($group) = ($splitTag =~ /^group-(.+)$/) if ($splitTag =~ /^group\-/);
    ($jid) = ($splitTag =~ /^jid-(.+)$/) if ($splitTag =~ /^jid\-/);
    ($resource) = ($splitTag =~ /^res-(.+)$/) if ($splitTag =~ /^res\-/);
  }

  $group = $self->UnescapeTag($group);
  $jid = $self->UnescapeTag($jid);
  $resource = $self->UnescapeTag($resource);

  my $icon;

  if ($type eq "group") {
    if ($self->{groups}->{$group}->{'__roster__:status'} == 1) {
      $icon = $main::GUI{Icons}->{Open};
    } else {
      $icon = $main::GUI{Icons}->{Closed}
    }
  }

  if ($type eq "resource") {
    $icon = $main::GUI{Icons}->{Resource};
  }

  if ($type eq "jid") {

    my $resource = $self->Resource($jid);

    if (defined($resource)) {
      my $presence =
        (($self->{resources}->{$jid}->{$resource}->{show} ne "") ?
	 $self->{resources}->{$jid}->{$resource}->{show} :
	 $self->{resources}->{$jid}->{$resource}->{type}
	);

      $icon = &main::jarlRosterIF_PresenceIcon($self,$presence,$jid);
    } else {
      $icon = &main::jarlRosterIF_PresenceIcon($self,"unavailable",$jid);
    }
  }

  $self->{canvas}->
    createRectangle(0,$self->{varsY}+1,
		    10000,$self->{varsY}+$self->{varsItem}->{Height},
		    -fill=>$types{$type}->{back},
		    -outline=>undef,
		    -tags=>[
			    $tag,
			    (($type eq "jid") ?
			     ("jidback", "${tag}-back") :
			     ()
			    ),
			    (($type eq "resource") ?
			     ("resback", "${tag}-back") :
			     ()
			    )
			   ]);

  $self->{canvas}->createImage(($indentLevel*15)+5,
                             $self->{varsY}+(int($self->{varsItem}->{Height}/2)),
			     -image=>$icon,
			     -anchor=>"w",
			     -tags=>[ $tag ]);

  $self->{canvas}->createText(($indentLevel*15)+($icon->width()+10),
                             $self->{varsY}+(int($self->{varsItem}->{Height}/2)),
			    -text=>$text,
                            (
                             (ref($self->{varsFont}) eq "Tk::Font") ?
                             (-font=>$self->{varsFont}) :
                             (
                               ($self->{varsFont} ne "") ?
                               (-font=>$self->{varsFont}) :
                               ()
                             )
                            ),
			    -fill=>$types{$type}->{fore},
			    -anchor=>"w",
			    -tags=>[ $tag , "text" ]);

  $self->{varsY} += $self->{varsItem}->{Height};
}


##############################################################################
#
# RegisterGroup - overload function to handle adding in a new group.  Sets up
#                 the bindings for interfacing with the Roster groups.
#
##############################################################################
sub RegisterGroup {
  my $self = shift;
  my ($group) = @_;

  if ($self->{canvas}->bind("group-${group}") eq "") {
    $self->{canvas}->
      bind("group-${group}",
	   "<Button-1>",
	   sub {
	     $self->{canvas}->
	       itemconfigure("jidback",
			     -fill=>$self->{varsJIDBackground});
	     $self->{canvas}->
	       itemconfigure("resback",
			     -fill=>$self->{varsResourceBackground});
	     $self->{varsSelectedJID} = undef;
	     $self->{varsSelectedTag} = undef;
	   }
	  );
    $self->{canvas}->
      bind("group-${group}",
	   "<Double-1>",
	   sub {
	     $self->Toggle($group);
	   }
	  );
  }
}


##############################################################################
#
# RegisterJID - overload to handle adding a new JID.  Setups the canvas
#               bindings for interfacing with the Roster.
#
##############################################################################
sub RegisterJID {
  my $self = shift;
  my ($group,$jid,$resource) = @_;

  my $tag = $self->CreateTag($group,$jid,$resource);

  if (defined($resource)) {
    $self->RegisterBalloon($tag,\$self->{resources}->{$jid}->{$resource}->{balloon});
  } else {
    $self->RegisterBalloon($tag,\$self->{jids}->{$jid}->{balloon});
  }

  return unless ($self->{canvas}->bind($tag) eq "");

  my $fullJID = $jid;
  $fullJID .= "/${resource}" unless ($resource eq "");

  $self->{canvas}->
    bind($tag,
	 "<Button-3>",
	 sub {
	   $self->{canvas}->
	     itemconfigure("jidback",
			   -fill=>$self->{varsJIDBackground});
	   $self->{canvas}->
	     itemconfigure("resback",
			   -fill=>$self->{varsResourceBackground});
	   $self->{canvas}->
	     itemconfigure("${tag}-back",
			   -fill=>$self->{varsSelectBackground});
	   $self->{varsSelectedJID} = $fullJID;
	   $self->{varsSelectedTag} = "${tag}-back";
	   &{$self->{varsJIDRightCommand}}($group,$jid,$resource)
	     if ($self->{varsJIDRightCommand} ne "");
	 }
	);

  $self->{canvas}->
    bind($tag,
	 "<Button-1>",
	 sub {
	   $self->{canvas}->
	     itemconfigure("jidback",
			   -fill=>$self->{varsJIDBackground});
	   $self->{canvas}->
	     itemconfigure("resback",
			   -fill=>$self->{varsResourceBackground});
	   $self->{canvas}->
	     itemconfigure("${tag}-back",
			   -fill=>$self->{varsSelectBackground});
	   $self->{varsSelectedJID} = $fullJID;
	   $self->{varsSelectedTag} = "${tag}-back";
	 }
	);

  $self->{canvas}->
    bind($tag,
	 "<Double-1>",
	 sub {
	   &{$self->{varsJIDLeftCommand}}($jid,$resource)
	     if ($self->{varsJIDLeftCommand} ne "");
	 }
	);
}


##############################################################################
#
# Clear - Clear the widget of all data
#
##############################################################################
sub Clear {
  my $self = shift;

  $self->{canvas}->delete("all");
  $self->SUPER::Clear();
}


1;
