# coding=utf-8

"""
Collects all number values from the db.serverStatus() command, other
values are ignored.

#### Dependencies

 * pymongo

#### Example Configuration

MongoDBCollector.conf

```
    enabled = True
    hosts = localhost:27017, alias1@localhost:27018, etc
```
"""

import diamond.collector
from diamond.collector import str_to_bool
import re
import zlib

try:
    import pymongo
except ImportError:
    pymongo = None

try:
    from pymongo import ReadPreference
except ImportError:
    ReadPreference = None


class MongoDBCollector(diamond.collector.Collector):
    MAX_CRC32 = 4294967295

    def __init__(self, *args, **kwargs):
        self.__totals = {}
        super(MongoDBCollector, self).__init__(*args, **kwargs)

    def get_default_config_help(self):
        config_help = super(MongoDBCollector, self).get_default_config_help()
        config_help.update({
            'hosts': 'Array of hostname(:port) elements to get metrics from'
                     'Set an alias by prefixing host:port with alias@',
            'host': 'A single hostname(:port) to get metrics from'
                    ' (can be used instead of hosts and overrides it)',
            'user': 'Username for authenticated login (optional)',
            'passwd': 'Password for authenticated login (optional)',
            'databases': 'A regex of which databases to gather metrics for.'
                         ' Defaults to all databases.',
            'ignore_collections': 'A regex of which collections to ignore.'
                                  ' MapReduce temporary collections (tmp.mr.*)'
                                  ' are ignored by default.',
            'collection_sample_rate': 'Only send stats for a consistent subset '
            'of collections. This is applied after collections are ignored via'
            ' ignore_collections Sampling uses crc32 so it is consistent across'
            ' replicas. Value between 0 and 1. Default is 1',
            'network_timeout': 'Timeout for mongodb connection (in seconds).'
                               ' There is no timeout by default.',
            'simple': 'Only collect the same metrics as mongostat.',
            'translate_collections': 'Translate dot (.) to underscores (_)'
                                     ' in collection names.',
            'ssl': 'True to enable SSL connections to the MongoDB server.'
                    ' Default is False'
        })
        return config_help

    def get_default_config(self):
        """
        Returns the default collector settings
        """
        config = super(MongoDBCollector, self).get_default_config()
        config.update({
            'path':      'mongo',
            'hosts':     ['localhost'],
            'user':      None,
            'passwd':      None,
            'databases': '.*',
            'ignore_collections': '^tmp\.mr\.',
            'network_timeout': None,
            'simple': 'False',
            'translate_collections': 'False',
            'collection_sample_rate': 1,
            'ssl': False
        })
        return config

    def collect(self):
        """Collect number values from db.serverStatus()"""

        if pymongo is None:
            self.log.error('Unable to import pymongo')
            return

        hosts = self.config.get('hosts')

        # Convert a string config value to be an array
        if isinstance(hosts, basestring):
            hosts = [hosts]

        # we need this for backwards compatibility
        if 'host' in self.config:
            hosts = [self.config['host']]

        # convert network_timeout to integer
        if self.config['network_timeout']:
            self.config['network_timeout'] = int(
                self.config['network_timeout'])

        # convert collection_sample_rate to float
        if self.config['collection_sample_rate']:
            self.config['collection_sample_rate'] = float(
                self.config['collection_sample_rate'])

        # use auth if given
        if 'user' in self.config:
            user = self.config['user']
        else:
            user = None

        if 'passwd' in self.config:
            passwd = self.config['passwd']
        else:
            passwd = None

        for host in hosts:
            matches = re.search('((.+)\@)?(.+)?', host)
            alias = matches.group(2)
            host = matches.group(3)

            if alias is None:
                if len(hosts) == 1:
                    # one host only, no need to have a prefix
                    base_prefix = []
                else: