'''Configuration parser

Copyright 2004-2005 AG Projects
'''

__all__ = ['Configuration', 'ConfigSection', 'Boolean', 'readSettings', 'getOption', 'dumpSection']

try:    from ConfigParser import SafeConfigParser as ConfigParser
except: from ConfigParser import ConfigParser
from utilities import *
import os

## If multiple ini files are specified, they are all read in order and each
## ini file overwrites the same options from the former ini files in the list
configFiles = ['mediaproxy.ini']

path = os.path.realpath((os.path.dirname(__file__) or '.') + '/..')

Configuration = ConfigParser()
Configuration.read(['%s/%s' % (path, f) for f in configFiles])


class ConfigSection:
    '''Basic class that defines a section in the configuration file. Should be inherited.'''
    _dataTypes = {}

class Boolean(int):
    __states = {'1': True, 'yes': True, 'true': True, 'on': True, 1: True, True: True,
                '0': False, 'no': False, 'false': False, 'off': False, 0: False, False: False}
    __objects = {} ## We want True and False to be singletons. Store them here.
    def __new__(typ, value):
        try: 
            value + 0
        except:
            try: value + ''
            except: raise TypeError, 'value should be a string'
            else: val = value.lower()
        else:
            val = value # eventually we can accept any int value by using 'not not value'
        try:
            state = Boolean.__states[val]
        except KeyError:
            raise ValueError, 'not a boolean: %s' % value
        if not state in Boolean.__objects:
            Boolean.__objects[state] = int.__new__(typ, state)
        return Boolean.__objects[state]
    def __repr__(self): return (self and 'True') or 'False'
    __str__ = __repr__


def readSettings(section, object):
    '''Update the object's attributes with values read from the given section in the config'''
    if section not in Configuration.sections():
        return
    for prop in dir(object):
        if prop[0]=='_':
            continue
        ptype = object._dataTypes.get(prop, eval('object.%s.__class__' % prop))
        try:
            val = Configuration.get(section, prop)
        except:
            pass
        else:
            try:
                if ptype is bool:
                    value = bool(Boolean(val))
                else:
                    value = ptype(val)
            except ValueError, why:
                warning("ignoring invalid config value: %s.%s=%s (%s)." % 
                        (section, prop, val, why))
            else:
                setattr(object, prop, value)

def getOption(section, option, default='', otype=str):
    try:
        value = Configuration.get(section, option)
    except:
        return default
    else:
        try:
            if otype is bool:
                return bool(Boolean(value))
            else:
                return otype(value)
        except ValueError:
            warning("ignoring invalid config value: %s.%s=%s (should be %s)." % 
                    (section, option, value, otype.__name__))
            return default

def dumpSection(object):
    print '%s:' % object.__name__
    for x in dir(object):
        if x[0] == '_': continue
        print '  %s = %s' % (x, eval('object.%s' % x))
    print ''

