# http://xkcd.com/276/
#
# Add statusbar item with one of (examples):
# - /statusbar window add -alignment right monospc
# - /statusbar window add -after act monospc
# 
# Changelog
# -- 2.1
# * Global monospc_naci removed
# * Per-channel monospc_naci_channels introduced
# * Loading problem for some users fixed
# 
# -- 2.0
# * First release

$VERSION = "2.1";
%IRSSI = (
    authors     => "Jonas Haggqvist",
    contact     => "rasher@rasher.dk",
    name        => "monospc",
    description => "Help you write evenly spaced lines",
    license     => "BSD license without advertising clause",
    url         => "http://rasher.dk/pub/",
);

use strict;
use encoding 'utf8';
use utf8;
use Irssi::TextUI;

# fixme: only the channelname is used as index
my %lastlength = ();
my $typedlength = -1;

# Remove whitespace from end of string
sub rtrim {
    my ($str) = @_;
    $str =~ s/\s*$//;
    return $str;
}

sub strip_nonprinting {
    my ($str) = @_;
    $str =~ s/[\x03][0-9]+(,[0-9]+)?//g; # no colors
    $str =~ s/[\x00-\x1f]//g; # no bold crap.
    return $str;
}

sub fix_string {
    my ($str) = @_;
    return strip_nonprinting(rtrim($str));
}

# Check length of a pubmsg and update %lastlength
sub check_length {
    my ($server, $msg, $nick, $address, $target) = @_;
    my $thislength = 0;
    $msg = fix_string($msg);
    utf8::upgrade($msg);
    
    $thislength += length($msg);
    $thislength += length($nick);
    $lastlength{$target} = $thislength;

    Irssi::statusbar_items_redraw('monospc');
}

# Check length of our own pubmsg and update %lastlength
sub check_length_own {
    my ($server, $msg, $target) = @_;
    my $thislength = 0;
    $msg = fix_string($msg);
    utf8::upgrade($msg);

    $thislength += length($server->{nick});
    $thislength += length($msg);

    # Find out if there's a nickmode character to count
    if (Irssi::settings_get_bool('show_nickmode') == 1 && Irssi::settings_get_bool('show_nickmode_empty') == 0) {
        my $channel = $server->channel_find($target);
        # fixme: Giving up :(
    }

    $lastlength{$target} = $thislength;
    Irssi::statusbar_items_redraw('monospc');
}

# Check length of what's currently in the input line
sub check_typing {
    my ($key) = @_;
    my $server = Irssi::active_server();
    my $msg = Irssi::parse_special("\$L");
    $msg = fix_string($msg);

    utf8::upgrade($msg);

    $typedlength = 0;
    $typedlength += length($server->{nick});
    $typedlength += length($msg);

    Irssi::statusbar_items_redraw('monospc');
}

sub check_enter {
    my ($key) = @_;
    my $server = Irssi::active_server();
    my $msg = Irssi::parse_special("\$L");
    my $window = Irssi::active_win();
    my $target = $window->{'active'}->{'name'};
    
    if ($lastlength{$target} lt 0) { return; }
    if ($msg =~ /^\//) { return; }
    if ($key != 10) { return; }

    my @chans = split(/[ ,]+/, Irssi::settings_get_str('monospc_nazi_channels'));
    foreach my $chan (@chans) {
        if (lc($chan) eq lc($target)) {
            $msg = fix_string($msg);
            utf8::upgrade($msg);
            my $thislength = 0;
            $thislength += length($server->{nick});
            $thislength += length($msg);

            if ($thislength != $lastlength{$target}) {
                Irssi::signal_stop();
            }
            last;
        }
    }
}

# Get contents of statusbar item
sub sb_contents {
    my $window = Irssi::active_win();
    my $target = $window->{'active'}->{'name'};

    if (!defined($lastlength{$target}) || $lastlength{$target} == -1) {
        return "??";
    }
    else {
        return sprintf("%d", $typedlength - $lastlength{$target});
    }
}

# Statusbar callback
sub monospc_sb {
    my ($item, $get_size_only) = @_;
    $item->default_handler($get_size_only, undef, sb_contents(), 1);
}

# Signal hooks
Irssi::signal_add('message public', 'check_length');
Irssi::signal_add('message own_public', 'check_length_own');
Irssi::signal_add_last('gui key pressed', 'check_typing');
Irssi::signal_add_first('gui key pressed', 'check_enter');

# Statusbar hooks
Irssi::statusbar_item_register('monospc', '{sb $0-}', 'monospc_sb');

# Settings
Irssi::settings_add_str('misc', 'monospc_nazi_channels', '');
