# Copyright (c) 2003 David Leadbeater released under GPLv2

# /lastgoto [lastlog options]
# /lastgoto or /lastlog + goes back in a previous search
# /lastgoto - goes forward

# I recommend something like /bind meta-f /lastgoto as it lets you search backwards quickly

# Treat this as a prototype version:
# It works ok-ish, apart from the lastlog and lastlog -clear making the text jump when you do /lastgoto.
# Also for more than 1 minute accuracy you need to enable timestamps with seconds.
# It should really be turned into a C module or intergrated into Irssi itself to get better intergration
# with all this stuff.

use strict;
use Irssi;
use Irssi::TextUI;

Irssi::command_bind("lastgoto", \&cmd_lastgoto);

my $position = 0;
my @finds = ( );

# BUGS: doesn't work if lastlog or timestamp format was changed

my $colours = '[' . join("", map(chr $_, 48 .. 63)) . ']';
my $internal = "\004";

sub cmd_lastgoto {
   my ($args, $server, $winit) = @_;

   $winit = Irssi::active_win unless ref $winit;

   if(!$args || $args eq '-' or $args eq '+') {
      if($args eq '-') {
         $args = -1;
      }else{
         $args = 1;
      }
      $position += $args;
      
      if($position < 0) {
         $position = -1;
         $winit->command("scrollback end");
         return;
      }
      if(not $finds[$position]) {
         $position = $#finds;
         return;
      }

      $winit->command("scrollback goto $finds[$position]");
      return;
   }

   return unless $args;
   
   @finds = ( );
   $position = 0;

   $winit->command("lastlog -force $args");

   my($view, $line);
	$view = Irssi::active_win->view;
   $line = $view->{buffer}->{cur_line};

   if(!ref $line) {
      $winit->print("No lines in buffer");
      return;
   }

   if($line->get_text(0) !~ /^End of Lastlog/) {
      $winit->print("Error getting lastlog data: " . $line->get_text(1));
      return;
   }

   my $lasttime;
   while(($line = $line->prev) && ref $line) {
      my $text = $line->get_text(1);
      last if $text =~ /^^D.{1,6}Lastlog/;
# We cannot use $line->{info}->{time} because this is when lastlog printed the line
      my $time = get_time_from_line($text);
      next if $lasttime eq $time or not $time;
      push @finds, $time;
      $lasttime = $time;
   }
   
   $winit->command("lastlog -clear");
   
   if(!@finds) {
      $winit->print("No matches found");
      return;
   }

   $winit->command("scrollback goto $finds[$position]");
}

sub get_time_from_line {
   my $text = shift;
   # Removes Irssi formatting (source: http://irssi.dgl.cx/paste.pl)
   $text =~ s{
      $internal
      (
       [a-i]
       |$colours / # fg
       |/ $colours # bg
      )
   }{}xg;

   if($text =~ /(\d{2}):?(\d{2}):?(\d{2})?/) {
      my $time = "$1:$2";
      $time .= ":$3" if $3;
      return $time;
   }

   return undef;
}

