use strict;
use Irssi;

use vars qw($VERSION %IRSSI);
$VERSION = '0.5';
%IRSSI   = (
    authors     => 'Mathieu Doidy',
    contact     => 'mdoidy at roulaize dot net',
    name        => 'enames',
    description => 'extend the names command to display away people grayed',
    license     => 'GPLv2',
    url         => 'http://irssi.roulaize.net',
    changed     => '14/11/2003',
);

sub _status {
    my ($nick) = @_;
    my $status =
      $nick->{'op'} ? 4 : $nick->{'halfop'} ? 3 : $nick->{'voice'} ? 2 : 1;
    return $status;
}

sub _max {
    my $ret = 0;
    foreach (@_) {
        my $ln = length( $_->{'nick'} ) + 4;
        $ret = $ln if $ln > $ret;
    }
    return $ret;
}

sub _sum {
    my $ret = 0;
    foreach (@_) { $ret += $_; }
    return $ret;
}

sub _get_max_column_count {
    my ( $max_w, $max_c, $item_extra, $item_min_size, @items ) = @_;
    my $items_count = scalar(@items);
    my ( @cols, @cols_w, $cols_r, $n );
    my $len = int( $max_w / ( $item_extra + $item_min_size ) );
    $len = 1 if $len <= 0;
    $max_c = $len if ( $max_c <= 0 || $len < $max_c );

    foreach ( 0 .. ( $max_c - 1 ) ) {
        my $n = $max_c - $_;
        $cols_r =
          $items_count < $n + 1 ? 1 : int( ( $items_count + $n - 1 ) / ($n) );

        foreach my $m ( 1 .. $max_c ) {
            $cols_w[$m] = 0;
            next if $m > $n;
            $cols_w[$m] =
              _max( @items[ ( $m - 1 ) * $cols_r .. $m * $cols_r - 1 ] );
        }

        return ( $n, $cols_r, @cols_w )
          if ( _sum(@cols_w) < $max_w
            && ( $n - 1 ) * ($cols_r) <= $items_count );
    }
}

sub _columns_sort_list {
    my ( $rows, @list ) = @_;

    my @sorted;

    foreach my $row ( 0 .. ( $rows - 1 ) ) {
        my $i = $row;
        while ( $list[$i] ) {
            push @sorted, $list[$i];
            $i += $rows;
        }
    }
    return @sorted;
}

sub _display_sorted_nicks {
    my ( $chan, @nicks ) = @_;
    my $window = Irssi::window_find_closest( $chan, MSGLEVEL_CLIENTCRAP );

    my $theme = $window->{theme} || Irssi::current_theme;
    my $format = $theme->get_format( 'fe-common/core', 'names' );

    my ( $count, $count_ops, $count_halfops, $count_voices, $count_normal )=(0,0,0,0,0);

    Irssi::theme_register(
        [
            'names',
            '{names_users Users {names_channel $0}}',
            'endofnames', '{line_start}{hilight Irssi:} {channel $0}: Total of {hilight $1} nicks {comment {hilight $2} ops, {hilight $3} halfops, {hilight $4} voices, {hilight $5} normal}'
        ]
    );

    $window->printformat( MSGLEVEL_CLIENTCRAP, 'names', $chan );

    my $max_w       = $window->{'width'} - 10;
    my $names_max_w = Irssi::settings_get_int("names_max_width");
    $max_w = $names_max_w if ( $names_max_w > 0 && $names_max_w < $max_w );
    $max_w = 10 if $max_w <= 0;

    my ( $cols, $rows, @cols_w ) =
      _get_max_column_count( $max_w,
        Irssi::settings_get_int("names_max_columns"),
        4, 3, @nicks );

    my @cnicks = _columns_sort_list( $rows, @nicks );

    my $last_col_rows = $rows - ( $cols * $rows - ( scalar @nicks ) );
    $last_col_rows = $rows if !$last_col_rows;

    my ( $col, $str, $row ) = (1);

    foreach (@cnicks) {
        my $mode =
          $_->{'op'} ? '@'
          : $_->{'halfop'} ? '%'
          : $_->{'voice'}  ? '+'
          : ' ';
        $count++;
        $_->{'op'} ? $count_ops++ : $_->{'halfop'}
          ? $count_halfops++
          : $_->{'voice'} ? $count_voices++ : $count_normal++;
        my $away = $_->{'gone'} ? '%w' : '';

        $str .= "%g[%n%_$mode%_$away$_->{'nick'}"
          . " " x ( $cols_w[$col] - 4 - length( $_->{'nick'} ) ) . "%g]%g";
        if ( ++$col == $cols + 1 ) {
            $window->print( $str, MSGLEVEL_CLIENTCRAP );
            $col = 1;
            $str = '';
            $row++;
            $cols-- if $row == $last_col_rows;
        }
        else { $str .= ' '; }
    }

    $window->print( $str, MSGLEVEL_CLIENTCRAP ) if $str;
    $window->printformat( MSGLEVEL_CLIENTCRAP, 'endofnames', $chan, $count,
        $count_ops, $count_halfops, $count_voices, $count_normal );
}

sub sig_stop { Irssi::signal_stop() }

sub enames {
    my ( $data, $server, $channel ) = @_;
    ## Irssi::signal_add_first( 'print text', 'sig_stop' );
    ## $channel->command("who");
    ## Irssi::signal_remove( 'print text', 'sig_stop' );
    my @nicks = sort {
        _status($b) <=> _status($a)
          || lc( $a->{'nick'} ) cmp lc( $b->{'nick'} )
    } $channel->nicks();
    _display_sorted_nicks( $channel->{'name'}, @nicks );
}

Irssi::command_bind( 'enames', 'enames' );
