class MongoKit(object):
    """This class is used to integrate `MongoKit`_ into a Flask application.

    :param app: The Flask application will be bound to this MongoKit instance.
                If an app is not provided at initialization time than it
                must be provided later by calling :meth:`init_app` manually.

    .. _MongoKit: http://namlook.github.com/mongokit/
    """

    def __init__(self, app=None):
        #: :class:`list` of :class:`mongokit.Document`
        #: which will be automated registed at connection
        self.registered_documents = []

        if app is not None:
            self.app = app
            self.init_app(self.app)
        else:
            self.app = None

    def init_app(self, app):
        """This method connect your ``app`` with this extension. Flask-
        MongoKit will now take care about to open and close the connection to 
        your MongoDB.
        
        Also it registers the
        :class:`flask.ext.mongokit.BSONObjectIdConverter`
        as a converter with the key word **ObjectId**.

        :param app: The Flask application will be bound to this MongoKit
                    instance.
        """
        app.config.setdefault('MONGODB_HOST', '127.0.0.1')
        app.config.setdefault('MONGODB_PORT', 27017)
        app.config.setdefault('MONGODB_DATABASE', 'flask')
        app.config.setdefault('MONGODB_USERNAME', None)
        app.config.setdefault('MONGODB_PASSWORD', None)
        app.config.setdefault('MONGODB_URL', 'mongodb://127.0.0.1:27071/')
        app.config.setdefault('MONGODB_CONNECTION_OPTIONS', {
            'auto_start_request': False
        })

        app.before_first_request(self._before_first_request)

        # 0.9 and later
        # no coverage check because there is everytime only one
        if hasattr(app, 'teardown_appcontext'):  # pragma: no cover
            app.teardown_appcontext(self._teardown_request)
        # 0.7 to 0.8
        elif hasattr(app, 'teardown_request'):  # pragma: no cover
            app.teardown_request(self._teardown_request)
        # Older Flask versions
        else:  # pragma: no cover
            app.after_request(self._teardown_request)

        # register extension with app only to say "I'm here"
        app.extensions = getattr(app, 'extensions', {})
        app.extensions['mongokit'] = self

        app.url_map.converters['ObjectId'] = BSONObjectIdConverter

        self.app = app

        self.mongokit_connection = Connection(
            host=app.config.get('MONGODB_HOST'),
            port=app.config.get('MONGODB_PORT'),
            **app.config.get('MONGODB_CONNECTION_OPTIONS', {})
        )
        self.mongokit_database = Database(self.mongokit_connection, app.config.get('MONGODB_DATABASE'))
        if app.config.get('MONGODB_USERNAME') is not None:
            auth_success = self.mongokit_database.authenticate(
                app.config.get('MONGODB_USERNAME'),
                app.config.get('MONGODB_PASSWORD')
            )
            if not auth_success:
                raise AuthenticationIncorrect('Server authentication failed')

    @property
    def connected(self):
        """Connection status to your MongoDB."""
        ctx = ctx_stack.top
        return getattr(ctx, 'mongokit_connection', None) is not None

    def _before_first_request(self):
        self.mongokit_connection.start_request()

    def _teardown_request(self, response):
        self.mongokit_connection.end_request()
        return response

    def __getattr__(self, name, **kwargs):
        return getattr(self._get_mongo_database(), name)

    def __getitem__(self, name):
        return self._get_mongo_database()[name]

    def _get_mongo_database(self):
        return self.mongokit_database