#!/usr/bin/perl -w
use strict;

use IO::Socket;
use BnDefs;

$| = 1;

my ($sock, $usernick, $userpass, $server);

$usernick = shift or do {
    print "`#ssfe#pNick: \n";
    chomp ($usernick = <STDIN>);
};
$userpass = shift or do {
    print "`#ssfe#PPass: \n";
    chomp ($userpass = <STDIN>);
};
$server = shift || 'battle.net';

$sock = conn ($usernick, $userpass);

my $pid = fork ();

if ($pid) {
    my ($buf);
    while (1) {
	chomp ($buf = <STDIN>);
	if ($buf eq '/quit') {
	    last;
	} elsif ($buf =~ m.^/eval .) {
	    $buf =~ s.^/eval ..;
	    eval $buf;
	    next;
	}
	$sock->send ($buf . "\r\n");
    }
    kill 1, $pid;
    $sock->close;
    exit 0;
} else {
    my (@buf) = ();
    while (1) {
	if (defined $sock->recv ($buf[0], 1024)) {
	    @buf = map {tr/\r\n//d;$_} split /\r\n/, $buf[0];
	    @buf = process (@buf);
	    for (@buf) {
		print $_, "\n" if defined $_;
	    }
	} else {
	    print "er, can't receive from socket, exiting...\n";
	    exit 1;
	}
    }
}

sub sl {
    $sock -> send (join ("", @_) . "\r\n");
}

sub conn {
    my ($n, $p) = @_;
    my ($sock);
    $sock = new IO::Socket::INET (PeerAddr => $server,
				  PeerPort => 6112,
				  Proto    => 'tcp')
	or die "couldn't open socket\n";

    defined $sock -> send ("c" . "\r\n")
	or die "Couldn't write to socket";
    ssleep (0.25);
    defined $sock -> send ($n . "\r\n")
	or die "Couldn't write nick to socket";
    ssleep (0.25);
    defined $sock -> send ($p . "\r\n")
	or die "Couldn't write pass to socket, perhaps someone is using\
your nick";
    ssleep (0.25);

    $sock;
}

sub ssleep {
    select undef, undef, undef, shift; # perldoc -f select
}

# This is where all the formatting happens
sub process {
    my (@raw) = @_;
    my (@ret) = ();
    for (@raw) {
	my ($id, $rest) = (split / /, $_, 3)[0,2];
	
	unless (defined $id) {
	    push @ret => undef;
	}
	elsif ($id !~ /^\d+$/) {
	    if (m[^/]) {
		push @ret => undef;
	    } else {
		push @ret => $_;
	    }
	} elsif (not defined $id or $id == $EID_JOIN
	    or $id == $EID_LEAVE) {
	    push @ret => undef;
	}
	elsif ($id == $EID_SHOWUSER) {
	    my ($nick, $client) = (split / /, $rest)[0,2];
	    push @ret => "*** $nick " . lc($client);
	}
	elsif ($id == $EID_TALK or $id == $EID_EMOTE or
	    $id == $EID_WHISPER or $id == $EID_WHISPERSENT) {
	    my ($nick, $msg) = (split / /, $rest, 3)[0,2];
	    $msg =~ s/^"(.*)"$/$1/;
	    if ($id == $EID_TALK) {
		push @ret => "<$nick> $msg";
	    } elsif ($id == $EID_EMOTE) {
		push @ret => "* $nick $msg";
	    } elsif ($id == $EID_WHISPER) { 
		print "`#ssfe#t/m $nick \n";
		push @ret => "[\cB$nick\cB] $msg";
	    } else {
		print "`#ssfe#t/m $nick \n";
		push @ret => ">\cB$nick\cB< $msg";
	    }
	}
	elsif ($id == $EID_CHANNEL) {
	    $rest =~ s/^"(.*)"$/$1/;
	    push @ret => "*\cB>\cB* You have joined $rest.";
	}
	elsif ($id == $EID_INFO) {
	    $rest =~ s/^"(.*)"$/$1/;
	    push @ret => "*** $rest";
	}
	elsif ($id == $EID_CHANNELRESTRICTED) {
	    push @ret => "*\cBE\cB* This channel is restricted.";
	}
	elsif ($id == $EID_CHANNELDOESNOTEXIST) {
	    push @ret => "\cB*E*\cB This channel doesn't exist.";
	} elsif ($id == $EID_ERROR) {
	    $rest =~ s/^"(.*)"$/$1/;
	    push @ret => "*\cBE\cB* $rest";
	} else {
	    push @ret => undef;
	}
    }
    @ret;
}
