import os

def get_home_dir():
    """
    Return user home directory
    """
    try:
        path = os.path.expanduser('~')
    except:
        path = ''
    for env_var in ('HOME', 'USERPROFILE', 'TMP'):
        if os.path.isdir(path):
            break
        path = os.environ.get(env_var, '')
    if path:
        return path
    else:
        raise RuntimeError('Please define environment variable $HOME')

#: home directory
HOMEDIR = get_home_dir()

NUMBA_CACHE_DIR = os.path.join(HOMEDIR, ".numba_cache")
os.environ["NUMBA_CACHE_DIR"] = NUMBA_CACHE_DIR #set it to os.environ.. so that numba can use it

import numpy as np

np_complex = np.complex64
np_float = np.float32
np_float = np.float32

DTYPEC = np.dtype(np_complex)
DTYPEF = np.dtype(np_float)

#DDM_VIDEO_WILDCARD= 'DM Video files (*.dmv)|*.dmv|HDF5 Video files (*.h5)|*.h5|Video files (*.mov)|*.mov,*.avi|TW Video files (*.twv)|*.twv|'
#USE_THREADING = True

def is_module_installed(name):
    """Checks whether module with name 'name' is istalled or not"""
    try:
        __import__(name)
        return True
    except ImportError:
        return False    
        
NUMBA_INSTALLED = is_module_installed("numba")
PYFFTW_INSTALLED = is_module_installed("pyfftw")
BLOSC_INSTALLED = is_module_installed("blosc")
NUMEXPR_INSTALLED = is_module_installed("numexpr")

#: default precision used in arithmetics
#PRECISION = "single"

def detect_number_of_cores():
    """
    detect_number_of_cores()

    Detect the number of cores in this system.

    Returns
    -------
    out : int
        The number of cores in this system.

    """
    import os
    # Linux, Unix and MacOS:
    if hasattr(os, "sysconf"):
        if "SC_NPROCESSORS_ONLN" in os.sysconf_names:
            # Linux & Unix:
            ncpus = os.sysconf("SC_NPROCESSORS_ONLN")
            if isinstance(ncpus, int) and ncpus > 0:
                return ncpus
        else:  # OSX:
            return int(os.popen2("sysctl -n hw.ncpu")[1].read())
    # Windows:
    if "NUMBER_OF_PROCESSORS" in os.environ:
        ncpus = int(os.environ["NUMBER_OF_PROCESSORS"])
        if ncpus > 0:
            return ncpus
    return 1  # Default

class DDMConfig(object):
    """DDM settings are here. You should use the set_* functions in the
    conf.py module to set these values"""
    def __init__(self):
        self.numba = NUMBA_INSTALLED
        self.pyfftw = PYFFTW_INSTALLED
        self.numexpr = NUMEXPR_INSTALLED
        self.ncores = detect_number_of_cores()
        self.nthreads = self.ncores
        self.verbose = 0
        self.precision = "single"
        
    def __getitem__(self, item):
        return self.__dict__[item]
        
    def __repr__(self):
        return repr(self.__dict__)

#: a singleton holding user configuration    
DDMConfig = DDMConfig()

def print_config():
    print(DDMConfig)

#setter functions for DDMConfig
def set_verbose(level):
    """Sets verbose level (0-3) used by compute functions."""
    out = DDMConfig.verbose
    DDMConfig.verbose = max(0,int(level))
    return out
    
def set_nthreads(num):
    """Sets number of threads used by compute functions."""
    out = DDMConfig.nthreads
    DDMConfig.nthreads = max(1,int(num))
    return out
    
def set_precision(precision):
    """Sets internal precision It can be either 'single' (default) or 'double'"""
    out = DDMConfig.precision
    values = ("single", "double")
    if precision in values:
        DDMConfig.precision = precision
    else:
        raise ValueError("Precision argument must be 'single' or 'double'")
    return out
        
def set_numba(ok):
    """Sets numba acceleration on or off. Returns previous setting."""
    out, ok = DDMConfig.numba, bool(ok) 
    if NUMBA_INSTALLED and ok:
        DDMConfig.numba = ok
        return out
    elif ok:
        import warnings
        warnings.warn("Numba is not installed so it can not be used! Please install numba.")
    DDMConfig.numba = False
    return out 
    
def set_pyfftw(ok):
    """Sets pyfftw acceleration on or off. Returns previous setting."""
    out, ok = DDMConfig.pyfftw, bool(ok) 
    if PYFFTW_INSTALLED and ok:
        DDMConfig.pyfftw = ok
        return out
    elif ok:
        import warnings
        warnings.warn("Pyfftw is not installed so it can not be used! Please install pyfftw.")
    DDMConfig.pyfftw = False
    return out            
    
def set_numexpr(ok):
    """Sets numexpr acceleration on or off. Returns previous setting."""
    out, ok = DDMConfig.numexpr, bool(ok) 
    if NUMEXPR_INSTALLED and ok: 
        DDMConfig.numexpr = ok
        return out
    elif ok:
        import warnings
        warnings.warn("Numexpr is not installed so it can not be used! Please install numexpr.")
    DDMConfig.numexpr = False
    return out


