# All this script adds is tab completion - it is blitzed services specific
# (as used on blitzed and OFTC), but mostly ircservices compatable.

# To use this script you will need some services aliases,
# /chanserv, etc, Run this command in irssi to add them:

# /eval alias aalias /alias $${0}serv /quote $${0}serv :$$$$0-\;/alias $$[-1]{0}s /quote $$[-1]{0}s :$$$$0-;aalias chan;aalias memo;aalias nick;aalias oper;aalias stat;unalias aalias

use strict;

my %services = (
   chanserv => {
      register => 'channel',
	  identify => 'channel',
	  set => {
     'channel' => 1, #hack#: this makes it add a channel.
	    founder => '',
		 successor => '',
		 password => '',
		 desc => '',
		 url => '',
		 email => '',
		 entrymsg => '',
		 topic => '',
		 keeptopic => 'toggle',
		 topiclock => 'toggle',
		 mlock => '',
		 private => 'toggle',
		 restricted => 'toggle',
		 secure => 'toggle',
		 secureops => 'toggle',
		 leaveops => 'toggle',
		 verbose => 'toggle',
		 autolimit => 'toggle',
		 clearbans => 'toggle'
	  },
	  access => {
		 'channel' => 1,
		 add => '',
		 del => '',
		 list => '',
		 view => '',
		 count => '',
	  },
	  levels => {
		 'channel' => 1,
		 set => {
			'autoop' => '',
			'autovoice' => '',
			'autodeop' => '',
			'nojoin' =>  '',
			'invite' => '',
			'akick' => '',
			'set' => '',
			'clear' => '',
			'unban' => '',
			'opdeop' => '',
			'acc-list' => '',
			'acc-change' => '',
			'memo-read' => '',
			'lev-list' => '',
			'lev-change' => '',
			'sync' => '',
			'memo-send' => '',
			'akick-list' => '',
		 },
		 dis => {
			'autoop' => '',
			'autovoice' => '',
			'autodeop' => '',
			'nojoin' => '',
			'invite' => '',
			'akick' => '',
			'set' => '',
			'clear' => '',
			'unban' => '',
			'opdeop' => '',
			'acc-list' => '',
			'acc-change' => '',
			'memo-read' => '',
			'lev-list' => '',
			'lev-change' => '',
			'sync' => '',
			'memo-send' => '',
			'akick-list' => '',
		 },
		 list => '',
		 'reset' => '',
	  },
	  akick => {
		 'channel' => 1,
		 add => '',
		 del => '',
		 list => '',
		 view => '',
		 enforce => '',
		 count => '',
	  },
	  info => '',
	  list => '',
	  invite => 'channel',
	  unban => 'channel',
	  op => 'channel',
	  deop => 'channel',
	  clear => {
		 channel => 1,
		 modes => '',
		 bans => '',
		 ops => '',
		 voices => '',
		 users => '',
	  },
	  sendpass => 'channel',
	  vop => {
		 'channel' => 1,
		 add => '',
	  },
	  aop => {
		 'channel' => 1,
		 add => '',
	  },
	  sop => {
		 'channel' => 1,
		 add => '',
	  },
	  sync => 'channel',
   },
   nickserv => {
     register => '',
	  identify => '',
	  access => {
	     add => '',
		 del => '',
		 list => '',
	  },
	  'link' => '',
	  'set' => {
	     password => '',
		 language => '',
		 url => '',
		 email => '',
		 enforce => 'toggle',
		 secure => 'toggle',
		 private => 'toggle',
		 hide => {
		    email => 'toggle',
			usermask => 'toggle',
			quit => 'toggle',
		 },
		 noop => 'toggle',
		 ircop => 'toggle'
	  },
	  recover => '',
	  release => '',
	  listlinks => '',
	  'unlink' => '',
	  ghost => '',
	  info => '',
	  list => '',
     listchans => '',
	  sendpass => '',
	  status => '',
	  regain => '',
   },
   memoserv => {
	  'send' => '',
	  globalsend => '',
	  opersend => '',
	  csopsend => '',
	  list => '',
	  'read' => '',
	  del => '',
	  set => {
		 notify => '',
		 limit => '',
	  },
   },
);

my %map = (
   cs => 'chanserv',
   ns => 'nickserv',
   ms => 'memoserv',
);

my $scommands = join("|", keys %map, keys %services);


sub complete {
   my ($complist, $window, $word, $linestart, $want_space) = @_;

   my $cmd = '[' . Irssi::settings_get_str('cmdchars') . ']';

   if($linestart =~ /^$cmd($scommands)(?: (.*))?/) {
      my $service = $1;
      my $text = $2;
      $service = $map{$service} if exists $map{$service};

      my $current = $services{$service};

      my $chan = 0;
      if(defined $text) {
         for(split ' ', $text) {
            next if /^\s*$/;

            if(not ref $current) {
               if($current eq 'toggle') {
                  push @$complist, qw/on off/;
               }elsif($current eq 'channel') {
                  $chan = 1;
                  last;
               }
               return;
            }

            if(exists $current->{$_}) {
               $current = $current->{$_};
            }
            next unless ref $current;

            if(exists $current->{channel} && !$chan) {
               $chan = 1;
            }elsif(exists $current->{channel}) {
               $chan = 0
            }
         }
      }

      if($chan) {
         my $name = (ref Irssi::active_win()->{active}
                        ? Irssi::active_win()->{active}->{name}
                        : undef);
         return if $word && $word !~ /^\Q$name\E/;
         push @$complist, $name;
         return;
      }

      if($word) {
         push @$complist, grep /^\Q$word\E/, keys %$current if ref $current;
      }else{
         push @$complist, keys %$current if ref $current;
      }
   }
}

Irssi::signal_add('complete word', \&complete);
