/*
        pass-msg:
        pass-msg: pass
        pass-msg: password
        pass-msg: 0211000001
        pass-msg: IRC|aEFJKMRTu
        pass-msg: P
        */
        public virtual void m_pass(IRCConnection connection, string[] ar)
        {
            // TODO: pass ist auch vom clienten möglich!
            Console.WriteLine(this + ": pass message");
            foreach (string s in ar)
            {
                Console.WriteLine("pass-msg: " +s);
            }

            if ((!(connection.GetType() == typeof(IRCConnection))) || ((IRCConnection)connection).PassSet)
            {
                connection.SendLine("ERROR: ERR_ALREADYREGISTRED");//connection.CloseLink(); // TO/DO: CloseLink soll RemoveConnetion in der Server-Klasse ersetzen/erweitern; RemoveConnation bleibt bestehen ruft aber nicht mehr connection.Dispose auf.
                return;
            }
            if (ar.Length < 3)
            {
                connection.SendLine("ERROR: ERR_NEEDMOREPARAMS");
                return;
            }

            if (false) // wenn passwort falsch
            {
                connection.SendLine("ERROR: Wrong Password, clossing link ...");
                this.CloseLink(connection); // CloseLink() kümmert sich um alles
                return;
            }
            ((IRCConnection)connection).PassSet = true;

            if (ar.Length > 3)
            {
                // TODO: TS-Server
                ;
            }
        }
        private void m_ping(IRCConnection connection, string[] par)
        {
            // :amd.tux PONG amd.tux :506855393
            if (par.Length < 2)
            {
                connection.SendLine(":ERROR ERR_NOORIGIN");
                return;
            }

            string name = ((SettingsHost)ServiceManager.Services[typeof(SettingsHost)]).Settings.ServerName;

            if (par.Length == 4)
                connection.SendLine(":"+name+" PONG " + par[3] + " :"+par[2]);
            else
                connection.SendLine(":"+name+" PONG " + name + " :"+par[2]);

            ((IRCConnection)connection).LastPing = DateTime.Now; // reset timer
        }
 /* orginal m_join		public virtual void m_join(IConnection connection, string[] par)
 {
     if (par.Length == 2)
     {
         if (par[1].Length > 1) // BUFIX emule "#" -channel
             this.Join(connection as IRCConnection, par[1]);
     }
 }
 */
 private void m_join(IRCConnection connection, string[] par)
 {
     Console.WriteLine("TO/DO: join command");
     if (connection is IRCUserConnection)
     {
         // TODO: if (RFC2812.IsJoinCommand);
         if (par.Length == 3)
         {
             if (par[1].Length > 2) // TODO: regex
                 this.Join((IRCUserConnection)connection, par[2]);
         }
     }
     else
         connection.SendLine("ERROR: type !IRCUserConnection");
 }
        // TODO: SendCommand anpassen
        /*
           ERR_NEEDMOREPARAMS              ERR_NOSUCHCHANNEL
           ERR_NOTONCHANNEL
        */
        private void m_part(IRCConnection src, string[] ar)
        {
            SimpleUser usr = null; // TODO

            if (this.IsServer(src))
            {
                throw new NotImplementedException("remote /part");
                //usr = this.Search(ar[0]); // TODO
                if (usr == null)
                {
                    return;
                }
            }
            else if (!this.IsUser(src))
            {
                // ERR
                src.SendLine("ERROR");
                return;
            }
            else
            {
                usr = (SimpleUser)src.SimpleClient;
            }

            #if false
            if (ar.Length > 4) // zuviel parameter
            {
                src.SendLine("to much parameters");
                return;
            }
            #endif
            if (ar.Length < 3)
            {
                // <command> :Not enough parameters
                src.SendCommand(ReplyCodes.ERR_NEEDMOREPARAMS, usr.NickName, ar[1], ":Not enough parameters");
                return;
            }

            Channel chan;
            string msg = string.Empty;
            if (ar.Length > 3)
                msg = ar[3];
            else
                msg = usr.NickName;

            string[] chans = ar[2].Split(new char[',']);
            foreach (string schan in chans)
            {
                chan = this.GetChannel(schan);
                if (chan == null)
                {
                    // <channel name> :No such channel
                    src.SendCommand(ReplyCodes.ERR_NOSUCHCHANNEL, usr.NickName, chan.Name, ":No such channel");
                    continue;
                }
                else if (!chan.HasUser(usr))
                {
                    // <channel> :You're not on that channel
                    src.SendCommand(ReplyCodes.ERR_NOTONCHANNEL, usr.NickName, chan.Name, ":You're not on that channel");
                    continue;
                }
                this.Part(usr, chan, msg);
            }
        }
        public virtual void m_who(IRCConnection connection, string[] ar)
        {
            // 0 == prefix
            // 1 == mask
            // 2 == z.B nur ops anzeigen
            if (this.IsServer(connection))
            {
                throw new NotImplementedException("remote /who");
            }
            else if (!this.IsUser(connection))
            {
                // ERR
                connection.SendLine("ERROR :Not registered");
                return;
            }

            if (ar.Length > 3) // zuviel parameter
            {
                connection.SendLine("ERROR :To much parameters");
                return;
            }

            Channel chan = null;
            bool onlyops = false;
            IRCUserConnection src = (IRCUserConnection)connection;

            if (ar.Length == 3)
            {
                // only ops
                if (ar[2] == "o")
                    onlyops = true;
            //				else
            //					connection.SendLine("ERR_NEEDMOREPARAMS_MSG");

            }
            if (ar.Length >= 2)
            {
                // TO/DO: Search Channel
                chan = GetChannel(ar[2]); // TODO: rfc
                if (chan != null)
                {
                    chan.SendWho(src, onlyops);

                    //src.SendCommand(ReplyCodes.RPL_ENDOFWHO, src.NickName, chan.Name, "End of /WHO list."); // jetzt in IRCChannel
                    return;
                }
            }

            foreach (IRCConnection client in this.Clients)
            {
                throw new NotImplementedException();
            }
            if (ar.Length == 1)
            {
                //return "*"
            }
            else
            {
                //return ar[1]
            }
        }
        public void RegisterUser(IRCConnection con)
        {
            if (con == null)
                throw new ArgumentNullException("con");

            lock (con)
            {
                if (con is IRCConnection)
                {
                    IRCUserConnection usr;
                    this.RemoveConnection(con);
                    usr = new IRCUserConnection(con);
                    this.AddConnection(usr);
                    // TODO: if (this.IsFull)
                    // TODO: this.AddUser(usr.SimpleUser);
                    // send bounce 005
                }
                else
                {
                    con.SendLine("ERROR :You could not register! Internal error");
                }
            }
        }
        public void RegisterServer(IRCConnection con, SimpleServer ser)
        {
            if (con == null)
                throw new ArgumentNullException("con");
            if (ser == null)
                throw new ArgumentNullException("ser");

            // TODO: ircservice mitteilen das zu diesem server keine verbindung mehr hergestellt werden muss
            lock (con)
            {
                if (con is IRCConnection)
                {
                    IRCServerConnection srv;
                    this.RemoveConnection(con);
                    srv = new IRCServerConnection(con, ser);
                    this.AddConnection(srv);
                    // TODO: mal sehen evtl. simpleserver erzeugen und mit AddServer hinzufügen
                    this.AddServer(ser);
                    IRCServerConnection.SendServer(srv);
                }
                else
                {
                    con.SendLine("ERROR: you could not register!; internal error");
                }
            }
        }
        // Command: NAMES
        // Parameters: [ <channel> *( "," <channel> ) [ <target> ] ]
        private void m_names(IRCConnection connection, string[] par)
        {
            if (connection.GetType() != typeof(IRCUserConnection))
            {
                // ERR
                connection.SendLine("ERROR");
                return;
            }
            if (par.Length > 4)
            {
                connection.SendLine("to much parameters"); //
                return;
            }
            IRCUserConnection src = (IRCUserConnection)connection;

            if (par.Length == 4)
            {
                throw new NotImplementedException("NAMES forward");

                // forward the request to another server
                IRCServerConnection[] srvs = this.SearchServer(par[3]);
                if (srvs.Length > 0)
                {
                    // [server name] :No such server
                    src.SendCommand(ReplyCodes.ERR_NOSUCHSERVER, src.NickName, par[3], ":No such server");
                }
                else
                {
                    //srvs[0].SendCommand(srvs.ServerName, src, "NAMES", par[2], par[3]);
                }
                return;
            }
            if (par.Length == 3)
            {
                Channel chan;
                if (par[2].IndexOf(',') != -1)
                {
                    chan = this.GetChannel(par[2]);
                    if (chan != null)
                    {
                        chan.SendNames(src);
                    }
                }
                else
                {
                    string[] chans = par[2].Split(new char[',']);
                    foreach (string schan in chans)
                    {
                        chan = this.GetChannel(schan);
                        if (chan == null)
                        {
                            continue;
                        }
                        chan.SendNames(src);
            #if false
                        src.SendCommand(ReplyCodes.RPL_NAMREPLY, src.NickName, "=", channel.Name, line);
                        src.SendCommand(ReplyCodes.RPL_ENDOFNAMES, src.NickName, channel.Name, ":End of NAMES list");
            #endif
                    }
                }
            }
            else
            {
                foreach (DictionaryEntry entry in this._channels)
                {
                    Channel chan = (Channel)entry.Value;
                    chan.SendNames(src);
                }

            #if false
                // TODO: Nun noch alle Clients ausgeben, die in keinem Channel sind
                //////
                src.SimpleClient.disadvantage++;
                src.SendCommand(ReplyCode.RPL_ENDOFNAMES, src.NickName, "*", ":End of NAMES list");
            #endif
            }
        }
        public virtual void m_server(IRCConnection connection, string[] ar)
        {
            // SERVER test.oulu.fi 1 :[tolsun.oulu.fi]
            // test.oulu.fi	== Server-Name
            // 1			== Hop-Count
            // [*]			== IP/DNS-Name

            Console.WriteLine(this + ": server message");
            foreach (string s in ar)
            {
                Console.WriteLine("server-msg: " +s);
            }
            if (connection is IRCUserConnection)
            {
                connection.SendLine("ERROR :already registered as client");
                return;
            }
            if (ar.Length < 4)
            {
                connection.SendLine("ERROR :SERVER needs more params");
                this.CloseLink(connection);
                return;
            }

            /*
            ** The SERVER message must only be accepted from either (a) a connection
            ** which is yet to be registered and is attempting to register as a
            ** server, or (b) an existing connection to another server, in  which
            ** case the SERVER message is introducing a new server behind that
            ** server.
            */
            if (connection is IRCServerConnection) // neu Server; wird uns von einen anderen Server mitgeteilt
            {
                SimpleServer rser = new SimpleServer();
                rser.HopCount = Convert.ToInt32(ar[3]);
                rser.UpLink = (IRCServerConnection)connection;
            }
            else // ein neuer Server versucht sich direkt zu registrieren
            {
                if (this.HasServer(connection.Socket.RemoteEndPoint)) // <-- HACK
                {
                    connection.SendLine("ERROR :Server already exits; Potential Damage To Network Intergrity");
                    this.CloseLink(connection);
                    return;
                }
            /*				if (this.HasServer(ar[2])) veraltet
                {
                    connection.SendLine("hostmask allrady in use");
                    this.CloseLink(connection);
                    return;
                }*/
                if (!((IRCConnection)connection).PassSet)
                {
                    connection.SendLine("ERROR :no permission");
                    this.CloseLink(connection);
                    return;
                }
                // anmerkung: wird nur gemacht wenn er sich direkt registriert
                if (!this.HasServerAccess(ar[2]))
                {
                    connection.SendLine("ERROR :no c/n lines");
                    this.CloseLink(connection);
                    return;
                }

                // all fine, register the new server
                SimpleServer ser = new SimpleServer(); // ausfüllen
                ser.HopCount = Convert.ToInt32(ar[3]);
                this.RegisterServer((IRCConnection)connection, ser);
            }
        }