use strict;
use Irssi;
use IPC::Open3;

Irssi::signal_add('message public', \&auto_date);
Irssi::settings_add_int('md', 'md_rainbow_offset', 0);
Irssi::command_bind('md', \&md_cmd);

sub auto_date {
	my ($server, $line, $nick, $host, $chan) = @_;

        $line =~ s/([\x02\x0F\x1F\x0E\x16\x1B]|\x03([0-9]{0,2})(,([0-9]{0,2}))?|\x04[0-9A-Fa-f]{6}(,([0-9A-Fa-f]){6})?)*//ig;
        $line =~ s/^\s*([a-f0-9]{32})\s*(?:-|8=+[eD])?\s*$/$1/ig;

	if ($line =~ /[a-f0-9]{32}/) {
		my $localDate = md(server => $server, chan => $chan);

		if ($line eq $localDate) {
			$server->command("msg $chan BOOM SYNCED");
		}
	}
}

sub md_cmd {
	my ($text, $server, $dest) = @_;
	md(server => $server, chan => $dest->{name});
}

sub md {
	my ($server, $chan); {
		my %opt = @_;
		$server = $opt{server};
		$chan = $opt{chan};
	}

	my $localDate = execute('date -u | md5');
	$localDate =~ s/\r?\n//g;
	$localDate =~ s/\s+-$//;

	$server->command(sprintf("msg %s %s", $chan, rainbow($localDate)));

	return $localDate;
}

sub execute {
	my $cmd = shift;

	my $pid = open3(\*WRITE, \*READ, \*READ, $cmd);
	close WRITE;
	my $text = join('', <READ>);
	close READ;

	waitpid($pid, 0);
	
	return $text;
}

sub rainbow {
	my $text = shift;

	# calculate stateful color offset
	my $state_offset = Irssi::settings_get_int("md_rainbow_offset");
	if ($state_offset < 0 or $state_offset > 20) {
		$state_offset = 0;
	} else {
		$state_offset++;
	}
	Irssi::settings_set_int("md_rainbow_offset", $state_offset);

	my @colormap = (4,4,7,7,5,5,8,8,9,9,3,3,10,10,11,11,12,12,2,2,6,6,13,13);

	# colorize.. thanks 2 sisko
	my $newtext;
	my $row = 0;
	foreach my $line (split(/\r\n/, $text)) {
		for (my $i = 0; $i < length($line); $i++) {
			my $chr = substr($line, $i, 1);
			my $color = $i + $row + $state_offset;
			$color = $color ?
				$colormap[$color %($#colormap-1)] :
				$colormap[0];
			if ($chr =~ /\s/) {
				$newtext .= $chr;
			} else {
				$newtext .= do_color($chr, $color);
			}
		}
		$row++;
	}

	return $newtext;
}

sub do_color {
	my $text = shift;
	my $fg_col = shift;

	my $ret = "\003$fg_col";

	my $ord = ord(substr($text, 0, 1));
	if (($ord >= 48 and $ord <= 57) or $ord == 44) {
		$ret .= "\26\26";
	}

	return ($ret . $text . "\x03\26\26");
}
