use strict;
use warnings;
use Xchat qw(:all);

my $TAB_NAME = "<privmsg>";

# copy messages instead of moving them
my $COPY_PM = 1;

# 0 = one tab for all networks
# 1 = one tab per network 
my $AGGREGATE_PER_NETWORK = 0;

# This is only used when $AGGREGATE_PER_NETWORK is 0
# %n = nick
# %N = network
my $NICK_FORMAT = "%n/%N";

register(
	"PM Aggregate",
	"1.0001",
	"Move or copy private messages to a single tab",
);

for my $event (
	"Private Message", "Private Message to Dialog",
	"Private Action", "Private Action to Dialog",
) {
	hook_print( $event, \&aggregate, { data => $event } );
}

sub aggregate {
	my ($nick, $msg, $id_text) = @{$_[0]};
	my $event = $_[1];

	# formatting must occur before tab switch
	unless( $AGGREGATE_PER_NETWORK ) {
		$nick = format_nick( $nick );
	}

	if( switch_tab( $TAB_NAME ) ) {
		emit_print( $event, $nick, $msg, $id_text );

		# if we are copying then prevent other plugins from seeing this event
		if( $COPY_PM ) {
			return EAT_PLUGIN;
		} else {
			return EAT_ALL;
		}
	}

	return EAT_NONE;
}

sub format_nick {
	my $nick = shift;

	my $format = $NICK_FORMAT;
	my %replacements = (
		n => $nick,
		N => network(),
	);
	
	my $search = join "", keys %replacements;
	$format =~ s/%([$search])/$replacements{$1}/g;

	return $format;
}

sub network {
	my $network = get_info( "network" );

	return $network if $network;

	my $id = get_info( "id" );

	my ($server_tab) = grep { $_->{id} == $id && $_->{type} == 1 }
		get_list "channels";

	if( $server_tab ) {
		return $server_tab->{channel};
	}

	return;
}

sub switch_tab {
	my $name = shift;
	my $opts = $AGGREGATE_PER_NETWORK ?
		{ type => 'dialog' } : { type => 'server' };

	my $context = get_tab( $name, $opts );

	if( $context ) {
		return set_context( $context );
	}

	return;
}

sub get_tab {
	my $tab_name = shift;
	my $opts = shift;
	my $type = $opts->{type};
	my $tab_opts = { type => $type };

	my $tab = find_tab( $tab_name, $tab_opts );

	unless( $tab ) {
		create_tab( $tab_name, $tab_opts );
		$tab = find_tab( $tab_name, $tab_opts );
	}

	return $tab;
}

sub find_tab {
	my $tab_name = shift;
	my $opts = shift;
	my $type = $opts->{type} eq 'server' ? 1 : 3;

	my $tab;

	if( $opts->{type} eq 'server' ) {
		($tab) = grep { $_->{channel} eq $tab_name && $_->{type} == $type }
			get_list( "channels" );
	} else {
		my $conn_id = get_info "id";
		($tab) = grep {
			$_->{channel} eq $tab_name
			&& $_->{type} == $type
			&& $_->{id} == $conn_id
		} get_list( "channels" );
	}

	if( $tab ) {
		return $tab->{context};
	}

	return;
}

sub create_tab {
	my $tab_name = shift;
	my $opts = shift;
	my $type = $opts->{type};

	if( $type eq 'server' ) {
		command( "NEWSERVER -noconnect $tab_name" );
	} else {
		command( "QUERY -nofocus $tab_name" )
	}

}
