public function reconnect()
    {
        // remember in which channels we are joined
        $channels = array();
        foreach ($this->_channels as $value) {
            if (empty($value->key)) {
                $channels[] = array('name' => $value->name);
            } else {
                $channels[] = array('name' => $value->name, 'key' => $value->key);
            }
        }

        $this->disconnect(true);

        while ($this->_autoretry === true
            && ($this->_autoretrymax == 0 || $this->_autoretrycount < $this->_autoretrymax)
            && $this->_updatestate() != SMARTIRC_STATE_CONNECTED
        ) {
            $this->_autoretrycount++;

            if ($this->_reconnectdelay > 0) {
                $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: delaying '
                    .'reconnect for '.$this->_reconnectdelay.' ms',
                    __FILE__, __LINE__
                );

                for ($i = 0; $i < $this->_reconnectdelay; $i++) {
                    $this->_callTimeHandlers();
                    usleep(1000);
                }
            }

            $this->_callTimeHandlers();
            $this->log(SMARTIRC_DEBUG_CONNECTION, 'DEBUG_CONNECTION: reconnecting...',
                __FILE__, __LINE__
            );

            if ($this->connect($this->_address, $this->_port, true) !== false) {
                break;
            }
        }

        if ($this->_updatestate() != SMARTIRC_STATE_CONNECTED) {
            return false;
        }

        $this->login($this->_nick, $this->_realname, $this->_usermode,
            $this->_username, $this->_password
        );

        // rejoin the channels
        foreach ($channels as $value) {
            if (isset($value['key'])) {
                $this->join($value['name'], $value['key']);
            } else {
                $this->join($value['name']);
            }
        }

        return $this;
    }