import couchdb
import sys
from couchdb.http import ResourceNotFound
from django.conf import settings
from django.core.cache import cache
from bilanci.utils import email_utils


def get(key):
    """
    Read all city budgets from the cache, and if not found,
    get that from couch (connecting if needed).

    :key: - the city slug (as for couchdb)
    """
    ret = cache.get(key)
    if ret is None:
        couch_db = connect()
        ret = couch_db.get(key)
        cache.set(key, ret)

    return ret


def get_connection_address(couchdb_server_settings=None):
    if couchdb_server_settings is None:
        couchdb_server_settings = settings.COUCHDB_SERVERS[settings.COUCHDB_DEFAULT_SERVER]

    server_connection_address = "http://"
    if 'user' in couchdb_server_settings and 'password' in couchdb_server_settings:
        server_connection_address += "{0}:{1}@".format(
            couchdb_server_settings['user'],
            couchdb_server_settings['password']
        )
    server_connection_address += "{0}:{1}".format(
        couchdb_server_settings['host'],
        couchdb_server_settings['port']
    )
    return server_connection_address


def get_server(couchdb_server_settings=None):
    server_connection_address = get_connection_address(couchdb_server_settings=couchdb_server_settings)
    couch_server = couchdb.Server(server_connection_address)
    return couch_server


def connect(couchdb_dbname=settings.COUCHDB_SIMPLIFIED_NAME, couchdb_server_settings=None):
    """
    Connect to the couchdb server and hook to the DB.
    Server and dbname are defined in the settings.

    Returns the pointer to the database or raise appropriate exceptions.
    """

    # open connection to couchdb server and hook to db
    couch_server = get_server(couchdb_server_settings=couchdb_server_settings)
    couch_db = couch_server[couchdb_dbname]

    return couch_db


class CouchBulkWriter(object):
    logger = None
    couchdb_dest = None
    object_list = []
    # bulk size is approx the size of 10 complete bilancio (preventivo and consuntivo)
    bulk_size = 2744300

    def __init__(self, logger, couchdb_dest):
        self.logger = logger
        self.couchdb_dest = couchdb_dest

    def write(self, obj):
        self.object_list.append(obj)
        if sys.getsizeof(self.object_list, default=0) > self.bulk_size:
            return self.flush()

        return None

    def close(self):
        if len(self.object_list) > 0:
            return self.flush()

    def flush(self):
        # writes bulk of bilanci to destination db and then empties the list of docs.
        self.logger.info("Writing bulk of {} docs to db".format(len(self.object_list)))

        return_values = self.couchdb_dest.update(self.object_list)

        for r in return_values:
            (success, docid, rev_or_exc) = r
            self.logger.debug("Write return values:{},{},{}".format(success,docid,rev_or_exc))
            if success is False:
                self.logger.critical("Document write failure! id:{} Reason:'{}'".format(docid, rev_or_exc))
                return False

        self.object_list=[]
        return True

import couchdb
import sys
from couchdb.http import ResourceNotFound
from django.conf import settings
from django.core.cache import cache
from bilanci.utils import email_utils


def get(key):
    """
    Read all city budgets from the cache, and if not found,
    get that from couch (connecting if needed).

    :key: - the city slug (as for couchdb)
    """
    ret = cache.get(key)
    if ret is None:
        couch_db = connect()
        ret = couch_db.get(key)
        cache.set(key, ret)

    return ret


def get_connection_address(couchdb_server_settings=None):
    if couchdb_server_settings is None:
        couchdb_server_settings = settings.COUCHDB_SERVERS[settings.COUCHDB_DEFAULT_SERVER]

    server_connection_address = "http://"
    if 'user' in couchdb_server_settings and 'password' in couchdb_server_settings:
        server_connection_address += "{0}:{1}@".format(
            couchdb_server_settings['user'],
            couchdb_server_settings['password']
        )
    server_connection_address += "{0}:{1}".format(
        couchdb_server_settings['host'],
        couchdb_server_settings['port']
    )
    return server_connection_address


def get_server(couchdb_server_settings=None):
    server_connection_address = get_connection_address(couchdb_server_settings=couchdb_server_settings)
    couch_server = couchdb.Server(server_connection_address)
    return couch_server


def connect(couchdb_dbname=settings.COUCHDB_SIMPLIFIED_NAME, couchdb_server_settings=None):
    """
    Connect to the couchdb server and hook to the DB.
    Server and dbname are defined in the settings.

    Returns the pointer to the database or raise appropriate exceptions.
    """

    # open connection to couchdb server and hook to db
    couch_server = get_server(couchdb_server_settings=couchdb_server_settings)
    couch_db = couch_server[couchdb_dbname]

    return couch_db


class CouchBulkWriter(object):
    logger = None
    couchdb_dest = None
    object_list = []
    # bulk size is approx the size of 10 complete bilancio (preventivo and consuntivo)
    bulk_size = 2744300

    def __init__(self, logger, couchdb_dest):
        self.logger = logger
        self.couchdb_dest = couchdb_dest

    def write(self, obj):
        self.object_list.append(obj)
        if sys.getsizeof(self.object_list, default=0) > self.bulk_size:
            return self.flush()

        return None

    def close(self):
        if len(self.object_list) > 0:
            return self.flush()

    def flush(self):
        # writes bulk of bilanci to destination db and then empties the list of docs.
        self.logger.info("Writing bulk of {} docs to db".format(len(self.object_list)))

        return_values = self.couchdb_dest.update(self.object_list)

        for r in return_values:
            (success, docid, rev_or_exc) = r
            self.logger.debug("Write return values:{},{},{}".format(success,docid,rev_or_exc))
            if success is False:
                self.logger.critical("Document write failure! id:{} Reason:'{}'".format(docid, rev_or_exc))
                return False

        self.object_list=[]
        return True

Read all city budgets from the cache, and if not found,     get that from couch (connecting if needed).      :key: - the city slug (as for couchdb) Connect to the couchdb server and hook to the DB.     Server and dbname are defined in the settings.      Returns the pointer to the database or raise appropriate exceptions. # open connection to couchdb server and hook to db # bulk size is approx the size of 10 complete bilancio (preventivo and consuntivo) # writes bulk of bilanci to destination db and then empties the list of docs.