import ctypes
import collections
import platform
import os

TYPES = {
 'Linux': {
  'loader': ctypes.CDLL,
  'functype': ctypes.CFUNCTYPE,
  'prefix': 'lib',
  'extension': '.so'
 },
 'Darwin': {
  'loader': ctypes.CDLL,
  'functype': ctypes.CFUNCTYPE,
  'prefix': 'lib',
  'extension': '.dylib'
 },
}
if platform.system() == 'Windows':
 TYPES['Windows'] = {
  'loader': ctypes.WinDLL,
  'functype': ctypes.WINFUNCTYPE,
  'prefix': "",
  'extension': '.dll'
 }

class LibraryLoadError(Exception): pass

def load_library(library, x86_path='.', x64_path='.', *args, **kwargs):
 lib = find_library_path(library, x86_path=x86_path, x64_path=x64_path)
 loaded = _do_load(lib, *args, **kwargs)
 if loaded is not None:
  return loaded
 raise LibraryLoadError('unable to load %r. Provided library path: %r' % (library, lib))

def _do_load(file, *args, **kwargs):
 loader = TYPES[platform.system()]['loader'] 
 return loader(file, *args, **kwargs)

def find_library_path(libname, x86_path='.', x64_path='.'):
 libname = '%s%s' % (TYPES[platform.system()]['prefix'], libname)
 if platform.machine() == 'x86_64':
  path = os.path.join(x64_path, libname)
 else:
  path = os.path.join(x86_path, libname)
 ext = TYPES[platform.system()]['extension']
 return '%s%s' % (path, ext)
  
def get_functype():
 return TYPES[platform.system()]['functype']
