use strict;
use Irssi 20040119.2359 ();
use vars qw($VERSION %IRSSI);
$VERSION = "1.20";
%IRSSI = (
    authors     => 'David Leadbeater, Timo Sirainen, Georg Lukas',
    contact     => 'dgl@dgl.cx, tss@iki.fi, georg@boerde.de',
    name        => 'usercount',
    description => 'Adds a usercount for a channel as a statusbar item',
    sbitems     => 'usercount',
    license     => 'GNU GPLv2 or later',
    url         => 'http://irssi.dgl.cx/',
    changes     => 'Only show halfops if server supports them',
);

# Once you have loaded this script run the following command:
# /statusbar window add usercount
# You can also add -alignment left|right option

# Settings:
# /toggle usercount_show_zero to show item even when there are no users
# /toggle usercount_show_ircops (default off)
# /toggle usercount_show_halfops (default on)

# you can customize the look of this item from theme file:
#  sb_usercount = "{sb %_$0%_ nicks ($1-)}";
#  sb_uc_ircops = "%_*%_$*";
#  sb_uc_ops = "%_@%_$*";
#  sb_uc_halfops = "%_%%%_$*";
#  sb_uc_voices = "%_+%_$*";
#  sb_uc_normal = "$*";
#  sb_uc_space = " ";


use Irssi::TextUI;

my ($ircops, $ops, $halfops, $voices, $normal, $total);
my ($timeout_tag, $recalc);

# Called to make the status bar item
sub usercount {
  my ($item, $get_size_only) = @_;
  my $wi = !Irssi::active_win() ? undef : Irssi::active_win()->{active};

  if(!ref $wi || $wi->{type} ne "CHANNEL") { # only works on channels
    return unless ref $item;
    $item->{min_size} = $item->{max_size} = 0;
    return;
  }

  if ($recalc) {
    $recalc = 0;
    calc_users($wi);
  }

  my $theme = Irssi::current_theme();
  my $format = $theme->format_expand("{sb_usercount}");
  if ($format) {
    # use theme-specific look
    my $ircopstr = $theme->format_expand("{sb_uc_ircops $ircops}",
          Irssi::EXPAND_FLAG_IGNORE_EMPTY);
    my $opstr = $theme->format_expand("{sb_uc_ops $ops}",
          Irssi::EXPAND_FLAG_IGNORE_EMPTY);
    my $halfopstr = $theme->format_expand("{sb_uc_halfops $halfops}",
          Irssi::EXPAND_FLAG_IGNORE_EMPTY);
    my $voicestr = $theme->format_expand("{sb_uc_voices $voices}", 
          Irssi::EXPAND_FLAG_IGNORE_EMPTY);
    my $normalstr = $theme->format_expand("{sb_uc_normal $normal}",
          Irssi::EXPAND_FLAG_IGNORE_EMPTY);
	my $space = $theme->format_expand('{sb_uc_space}',
         Irssi::EXPAND_FLAG_IGNORE_EMPTY);
	$space = " " unless $space;

    my $str = "";
    $str .= $ircopstr.$space if defined $ircops;
    $str .= $opstr.$space  if defined $ops;
    $str .= $halfopstr.$space if defined $halfops;
    $str .= $voicestr.$space if defined $voices;
    $str .= $normalstr.$space if defined $normal;
    $str =~ s/\Q$space\E$//;

    $format = $theme->format_expand("{sb_usercount $total $str}",
				    Irssi::EXPAND_FLAG_IGNORE_REPLACES);
  } else {
    # use the default look
    $format = "{sb \%_$total\%_ nicks \%c(\%n";
    $format .= '*'.$ircops.' ' if (defined $ircops);
    $format .= '@'.$ops.' ' if (defined $ops);
    $format .= '%%'.$halfops.' ' if (defined $halfops);
    $format .= "+$voices " if (defined $voices);
    $format .= "$normal " if (defined $normal);
    $format =~ s/ $//;
    $format .= "\%c)}";
  }

  $item->default_handler($get_size_only, $format, undef, 1);
}

sub calc_users() {
  my $channel = shift;
  my $server = $channel->{server};

  $ircops = $ops = $halfops = $voices = $normal = 0;
  for ($channel->nicks()) {
    if ($_->{serverop}) {
      $ircops++;
	}

    if ($_->{op}) {
      $ops++;
	} elsif ($_->{halfop}) {
	   $halfops++;
    } elsif ($_->{voice}) {
      $voices++;
    } else {
      $normal++;
    }
  }

  $total = $ops+$halfops+$voices+$normal;
  
  if (!Irssi::settings_get_bool('usercount_show_zero')) {
    $ircops = undef if ($ircops == 0);
    $ops = undef if ($ops == 0);
    $halfops = undef if ($halfops == 0);
    $voices = undef if ($voices == 0);
    $normal = undef if ($normal == 0);
  }

  # Server doesn't support halfops? 
  if($server->can('isupport') && $server->isupport("PREFIX") !~ /\%/) {
     $halfops = undef;
  } else {
     $halfops = undef unless Irssi::settings_get_bool('usercount_show_halfops');
  }

  $ircops = undef unless Irssi::settings_get_bool('usercount_show_ircops');
}

sub refresh {
   if ($timeout_tag > 0) {
      Irssi::timeout_remove($timeout_tag);
      $timeout_tag = 0;
   }
   Irssi::statusbar_items_redraw('usercount');
}

sub refresh_check {
   my $channel = shift;
   my $wi = ref Irssi::active_win() ? Irssi::active_win()->{active} : 0;

   return unless ref $wi && ref $channel;
   return if $wi->{name} ne $channel->{name};
   return if $wi->{server}->{tag} ne $channel->{server}->{tag};

   # don't refresh immediately, or we'll end up refreshing 
   # a lot around netsplits
   $recalc = 1;
   Irssi::timeout_remove($timeout_tag) if ($timeout_tag > 0);
   $timeout_tag = Irssi::timeout_add(500, 'refresh', undef);
}

sub refresh_recalc {
  $recalc = 1;
  refresh();
}

$recalc = 1;
$timeout_tag = 0;

Irssi::settings_add_bool('usercount', 'usercount_show_zero', 1);
Irssi::settings_add_bool('usercount', 'usercount_show_ircops', 0);
Irssi::settings_add_bool('usercount', 'usercount_show_halfops', 1);

Irssi::statusbar_item_register('usercount', undef, 'usercount');
Irssi::statusbars_recreate_items();

Irssi::signal_add_last('nicklist new', 'refresh_check');
Irssi::signal_add_last('nicklist remove', 'refresh_check');
Irssi::signal_add_last('nick mode changed', 'refresh_check');
Irssi::signal_add_last('setup changed', 'refresh_recalc');
Irssi::signal_add_last('window changed', 'refresh_recalc');
Irssi::signal_add_last('window item changed', 'refresh_recalc');

