private void HandleChannelModeChange(IReceiveMessage message)
        {
            Channel channel = message.Receiver as Channel;

            String[] split = message.Contents.Split(new[] { ' ' }, 2);
            if (split.Length == 1)
            {
                channel.Modes.ParseAndApply(split[0]);
            }
            else
            {
                ModeChange[] changes   = Mode.Parse(split[0]);
                String[]     nicknames = split[1].Split(' ');

                if (changes.Length != nicknames.Length)
                {
                    _logger.Error("Length of changes does not match length of nicknames.");
                    return;
                }

                for (int i = 0; i < changes.Length; ++i)
                {
                    ChannelUser channelUser = channel.GetUser(nicknames[i]) as ChannelUser;
                    channelUser.Modes.Apply(changes[i]);
                }
            }
        }
        private void HandleWhoReply(IReceiveMessage message)
        {
            String[] split = message.Contents.Split(new[] { ' ' }, 9);

            if (split.Length != 9)
            {
                _logger.Error("Who reply with less than 9 parameters.");
                return;
            }

            Channel     channel     = GetChannel(split[1]) as Channel;
            User        user        = GetUser(split[5]) as User;
            ChannelUser channelUser = channel.GetUser(user.Name) as ChannelUser;

            user.Identity.Ident.Value = split[2];
            user.Identity.Host.Value  = split[3];
            user.Network.Value        = GetNetwork(split[4]);

            bool away         = false;
            bool serverOp     = false;
            bool channelVoice = false;
            bool channelOp    = false;

            foreach (char c in split[6])
            {
                switch (c)
                {
                case 'H': away = false; break;

                case 'G': away = true; break;

                case '*': serverOp = true; break;

                case '@': channelOp = true; break;

                case '+': channelVoice = true; break;
                }
            }

            user.Away.Value = away;

            // TODO: proper server operator mode.
            if (serverOp)
            {
                user.Modes.AddMode('o');
            }
            else
            {
                user.Modes.RemoveMode('o');
            }

            if (channelVoice)
            {
                channelUser.Modes.AddMode('v');
            }
            else
            {
                channelUser.Modes.RemoveMode('v');
            }

            if (channelOp)
            {
                channelUser.Modes.AddMode('o');
            }
            else
            {
                channelUser.Modes.RemoveMode('o');
            }

            // TODO: hop count.

            user.RealName.Value = split[8];
        }