# Based on http://github.com/avar/irssi-bitlbee-facebook-rename
#
# Changes:
#   - completely silent rename
#   - limits nick length to 21 characters
#   - adds _fb to the username
#   - no longer saves after every nick change
#
# Todo:
#   - prevent nick clashes

use strict;
use warnings;
use Irssi;
use Irssi::Irc;
use Text::Unidecode;
use Encode qw(decode);

our $VERSION = '0.03';
our %IRSSI = (
  authors => do { use utf8; 'Ævar Arnfjörð Bjarmason' },
    contact => 'avarab@gmail.com',
    name    => 'facebook-bitlbee-rename',
    description => 'Rename XMPP chat.facebook.com contacts in bitlbee to human-readable names',
    license => 'GPL',
);

my $bitlbeeChannel = "&bitlbee";
my $bitlbee_server_tag = "bitlbee";
my %nicksToRename = ();

sub message_join {
  # "message join", SERVER_REC, char *channel, char *nick, char *address
  my ($server, $channel, $nick, $address) = @_;
  my ($username, $host) = split /@/, $address;

  if ($host eq 'chat.facebook.com' and $channel =~ m/$bitlbeeChannel/ and $nick =~ m/$username/) {
    $nicksToRename{$nick} = $channel;
    $server->command("whois -- $nick");
  }
}

sub intercept_message {
  my ($server, $msg, $target) = @_;
  my $renamecommand = 'rename';

  # Find out what channel we are currently on
  my $currentserver = $server->{tag};

  # Only act if we're on the Bitlbee channel, on the Bitlbee chatnet
  return if $currentserver ne $bitlbee_server_tag;
  return if $target ne $bitlbeeChannel;

  if ($msg =~ m/^($renamecommand)/) {
    # Yup, we are renaming, so don't output anything
    Irssi::signal_stop();
  }
}

sub intercept_response {
  my ($server, $msg, $nick, $address, $target) = @_;

  # Find out what channel we are currently on
  my $currentserver = $server->{tag};

  # Only act if we're on the Bitlbee channel, on the Bitlbee chatnet
  return if $currentserver ne $bitlbee_server_tag;
  return if $target ne $bitlbeeChannel;

  my $renameresponse = 'Nick successfully changed';
  if ($msg =~ m/^Nick successfully changed/) {
    # Server just confirmed the rename, but we don't care
    Irssi::signal_stop();
  }

  # The following bit is buggy as hell, so leaving it disabled until I come up with a better solution
  #
  #if ($msg =~ m/^Nick `(.*)' already exists/i) {
  #  # Nick already exists, so we add a character
  #  my $ircname = $1 . '2';
  #
  #  # Try another rename
  #  $server = Irssi::server_find_tag( $bitlbee_server_tag );
  #  $server->command("msg $bitlbeeChannel rename $nick $ircname");
  #}
}


sub whois_data {
  my ($server, $data) = @_;
  my ($me, $nick, $user, $host) = split(" ", $data);

  if (exists($nicksToRename{$nick})) {
    my $channel = $nicksToRename{$nick};
    delete($nicksToRename{$nick});

    my $ircname = substr($data, index($data,':')+1);

    $ircname = munge_nickname( $ircname );

    if ($ircname ne $nick) {
      # Do the actual renaming
      $server->command("msg $channel rename $nick $ircname");

      # Save the new nicknames (disabled, it's annoying)
      #$server->command("msg $channel save");
    }
  }
}

sub munge_nickname {
  my ($nick) = @_;

  $nick = decode('utf8', $nick);
  $nick =~ s/[- ]/_/g;
  $nick = unidecode($nick); 
  $nick =~ s/[^A-Za-z0-9-]//g;

  # Trimming the nickname a bit more, since we want to add '_fb' to the nick later
  $nick = substr $nick, 0, 21;

  # Rename the user, but add '_fb' to their nick
  $nick = $nick . '_fb';

  return $nick;
}

Irssi::signal_add_first 'message join' => 'message_join';
Irssi::signal_add_first 'event 311' => 'whois_data';

# Intercept the renaming of users when we initiate it
Irssi::signal_add_first 'message own_public' => 'intercept_message';
# Intercept the Bitlbee reply as well
Irssi::signal_add_first 'message public' => 'intercept_response';
