# SERVER-1988: regex based filesystem exclusion for server_disk and
# infra_filesystem. A filesystem whose mount point or device id matches
# filesystem.exclude.pattern (re.search) is dropped before the packs are built,
# so matched filesystems are never sent. An invalid pattern is logged once
# per pattern value and then treated as if the option was not set, so a
# bad regex can never break collection.
import re
import whatap.agent.conf.configure as config
import whatap.util.logging_util as logging_util

_cachedPattern = None
_cachedRegex = None
_badPattern = None


def _getExcludeRegex():
    global _cachedPattern, _cachedRegex, _badPattern
    pattern = config.GetConfig().getProperty('FilesystemExcludePattern', '')
    if pattern is None:
        pattern = ''
    if not isinstance(pattern, basestring):
        # try_cast_value may turn a numeric-looking pattern into int/float.
        # basestring keeps unicode patterns intact (str() on non-ASCII
        # unicode would raise UnicodeEncodeError).
        pattern = str(pattern)
    pattern = pattern.strip()
    if not pattern:
        _cachedPattern = None
        _cachedRegex = None
        return None
    if pattern == _cachedPattern:
        return _cachedRegex
    if pattern == _badPattern:
        return None
    try:
        regex = re.compile(pattern)
    except Exception, e:
        logging_util.error(
            "[FilesystemExclude] invalid filesystem.exclude.pattern '{}': {}".format(pattern, e))
        _badPattern = pattern
        _cachedPattern = None
        _cachedRegex = None
        return None
    _cachedPattern = pattern
    _cachedRegex = regex
    _badPattern = None
    return regex


def FilterFileSystems(diskperfs):
    # Returns diskperfs with excluded filesystems removed. Never raises:
    # on any unexpected error the original list is returned unfiltered.
    try:
        regex = _getExcludeRegex()
        if not regex or not diskperfs:
            return diskperfs
        filtered = []
        for diskperf in diskperfs:
            mountPoint = getattr(diskperf, 'mountPoint', None) or ''
            deviceId = getattr(diskperf, 'deviceId', None) or ''
            if regex.search(mountPoint) or regex.search(deviceId):
                continue
            filtered.append(diskperf)
        return filtered
    except Exception, e:
        logging_util.error("[FilesystemExclude] filter failed: {}".format(e))
        return diskperfs
