#!/usr/bin/perl -w
use strict;
use Gaim::Log::Parser 0.04;
use Gaim::Log::Finder;
use Sysadm::Install 0.23 qw(:all);
use Lingua::StopWords;
use Text::Language::Guess;
use Log::Log4perl qw(:easy);
use Text::Wrap qw(fill $columns);
use URI::Find;
use IMAP::Client;
use DateTime::Format::Mail;

my $mailbox = "im_mailbox";
my $tzone   = "America/Los_Angeles";
my $min_age = 3600;
my $sleep   = 3600;

my %im_stopwords = map { $_ => 1 } qw(
maybe thanks thx doesn hey put already 
said say would can could haha hehe see 
well think like heh now many lol doh );

Log::Log4perl->easy_init({
  level => $DEBUG, category => "main",
  file  => ">>$ENV{HOME}/.gaim2imap.log"
});

my $PW = password_read("password: ");

my $pid = fork();
die "fork failed" if ! defined $pid;
exit 0 if $pid;

dbmopen my %SEEN, 
        "$ENV{HOME}/.gaim/.seen", 0644 or
     LOGDIE "Cannot open dbm file ($!)";

$SIG{TERM} = sub { INFO "Exiting"; 
    dbmclose %SEEN;
    exit 0;
};

while(1) {
    update();
    INFO "Sleeping $sleep secs";
    sleep $sleep;
}

###########################################
sub update {
###########################################
  DEBUG "Connecting to IMAP server";

  my $imap = new IMAP::Client();
  $imap->onfail('ABORT');
  $imap->connect(PeerAddr => 'localhost',
      ConnectMethod => 'PLAIN');

  my $u = getpwuid $>;
  $imap->authenticate($u, $PW);

  my $finder = Gaim::Log::Finder->new(
    callback => sub { 
      my($self, $file, $protocol, 
         $from, $to) = @_;

      return 1 if $from eq $to;

      my $mtime = (stat $file)[9];
      my $age = time() - $mtime;

      return 1 if $SEEN{$file} and
                  $SEEN{$file} == $mtime;

      if($age < $min_age) {
          INFO "$file: Too recent ($age)";
          return 1;
      }

      $SEEN{$file} = $mtime;
      INFO "Processing log file: $file";
      my($subject, $formatted, $epoch) = 
                   chat_process($file);

      imap_add($imap, $mailbox, $epoch, 
               "$to\@gaim", "", $subject, 
               $formatted);
  });

  $finder->find();
}

###########################################
sub chat_process {
###########################################
  my($file) = @_;

  my $parser = Gaim::Log::Parser->new(
    file => $file,
  );
      # Search+delete URL processor
  my $urifind = URI::Find->new(sub {""});

  my $text      = "";
  my $formatted = "";
  my $urifound;
  $Text::Wrap::columns = 70;

  while(my $m = $parser->next_message()) {
    my $content = $m->content();
    $content =~ s/\n+/ /g;
    $formatted .= fill("", "  ", 
      nice_time($m->date()) . " " .
      $m->from() . ": " . $content) . "\n\n";

    $urifound = 
        $urifind->find(\$content);
    $text .= " " . $content;
  }

  my $guesser = Text::Language::Guess->
            new(languages => ['en', 'de']);

  my $lang = 
    $guesser->language_guess_string($text);

  $lang = 'en' unless $lang;
  DEBUG "Guessed language: $lang\n";

  my $stopwords = 
    Lingua::StopWords::getStopWords($lang);

  my %words;

  while($text =~ /\b(\w+)\b/g) {
    my $word = lc($1);
    next if $stopwords->{$word};
    next if $word =~ /^\d+$/;
    next if length($word) <= 2;
    next if exists $im_stopwords{$word};
    $words{$word}++;
    $words{$word} += 3 if length $word > 6;
  }

  my @weighted_words = sort { 
    $words{$b} <=> $words{$a} 
  } keys %words;

  my $subj = ($urifound ? '*L*' : "");
  my $char = "";

  while(@weighted_words and length($subj) + 
      length($char . 
         $weighted_words[0]) <= 70) {
    $subj .= $char .  shift @weighted_words;
    $char = ", ";
  }

  return($subj, $formatted, 
         $parser->{dt}->epoch());
}

###########################################
sub imap_add {
###########################################
  my($imap, $mailbox, $date, 
     $from, $to, $subject, $text) = @_;

  $date = 
   DateTime::Format::Mail->format_datetime(
     DateTime->from_epoch(
         epoch => $date, 
         time_zone => $tzone));

  my $message = "Date: $date\n" .
    "From: $from\n" .
    "To: $to\n" .
    "Subject: $subject\n\n$text";

  my $fl = $imap->buildflaglist();
  $imap->append($mailbox, $message, $fl);
}
