import ConfigParser
import os
from contextlib import closing

all = ['config', 'dir_map', 'segment_info', 'db_info']


class ConfigOption(object):
    def __init__(self, name, section = 'default', converter = None, default = None):
        self.name = name
        self.section = section
        self.converter = converter or (lambda x: x)
        self.default = default
        
        if section == 'default':
            self.attr_name = name
        else:
            self.attr_name = '%s_%s' % (section, name)


class Config(object):
    def __init__(self):
        object.__setattr__(self, '_config_options', dict())
        
        self._config_parser = ConfigParser.SafeConfigParser()
        _config_path = None 
        
        with closing(open(os.path.join(__file__, '..', '..', 'project_data', 'current_project.txt'), 'rb')) as file:
            line = file.readline()
            if line: _config_path = line
        
        if _config_path:
            self._config_parser.read(os.path.normpath(_config_path))
        else:
            #create config database 
            #create_db('CCHR_config')
            
            self._config_parser.read(os.path.join(__file__, '..', 'bjs.config'))
            
    def add_option(self, name, section = 'default', converter = None, default = None):
        option = ConfigOption(name = name, section = section, converter = converter, default = default)
        if option.attr_name in self._config_options:
            return
        
        self._config_options[option.attr_name] = option
        if hasattr(self, option.attr_name):
            value = getattr(self, option.attr_name)
        elif self._config_parser.has_option(option.section, option.name):
            value = self._config_parser.get(option.section, option.name)
        else:
            value = option.default
            
        if converter:
            value = converter(value)
        
        setattr(self, option.attr_name, value)
        
    def __setattr__(self, name, value):
        option = self._config_options.get(name)
        if option:
            value = option.converter(value)
            
        object.__setattr__(self, name, value)


def _bool(v):
    if isinstance(v, basestring):
        v = v.lower()
        
    return v not in ['false', 'no', 'f', '0', False]


def _int(v):
    return int(v)


def _as_dir(v):
    return r'%s' % v

config = Config()

#add int config options, default section
for __opt in ['follow_period', 'current_set', 'cores', 'transform_threads']:
    config.add_option(__opt, converter=_int)

#add str config options, debug section
for opt in ['verbose', 'validate_regex_rules']:
    config.add_option(opt, section='debug')

#add bool config options, debug section
config.add_option('halt_on_error', section='debug', converter=_bool)

#add directory config options, default section 
for opt in ['out_dir', 'in_dir', 'review_dir', 'log_dir', 'meta_dir', 'rule_dir', 'report_dir', 'offense_dir', 
            'admrec_dir', 'xwalk_out_dir', 'stable_dir', 'tmp_out_dir',
            'root_dir', 'project_dir']:
    config.add_option(opt, converter=_as_dir)

#add the db options
config.add_option('host', section='db')
config.add_option('port', section='db', converter=_int)

#add security info
config.add_option('HMAC_KEY', section='security')

for sec in ['db_stand', 'db_recid', 'db_subject']: 
    for opt in ['name', 'user', 'pass', 'collate', 'encoding']:
        config.add_option(opt, section=sec)
    config.add_option('dir', section=sec, converter=_as_dir)

for sec in ['subject', 'arrest', 'sentence', 'supervision', 'demographic', 'prosecution']:
    section = 'segment_%s' % sec
    for opt in ['label', 'region_var']:
        config.add_option(opt, section=section)
    for opt in ['id', 'priority']:
        config.add_option(opt, section=section, converter=_int)
    #config.add_option('load', section=section, converter=_bool)

dir_map = dict(in_dir=config.in_dir, out_dir=config.out_dir, log_dir=config.log_dir,
               metadata_dir=config.meta_dir, report_dir=config.report_dir, review_dir=config.review_dir)

for dir in ['pre_process_rules', 'process_rules']:
    dir_map['%s_dir' % dir] = os.path.normpath(os.path.join(config.rule_dir, dir))
    

segment_info = {'subject': {'id': config.segment_subject_id,
                            'label': config.segment_subject_label,
                            'region_var': config.segment_subject_region_var,
                            'priority': config.segment_subject_priority},
                'arrest': {'id': config.segment_arrest_id,
                           'label': config.segment_arrest_label,
                           'region_var': config.segment_arrest_region_var,
                           'priority': config.segment_arrest_priority},
                'sentence': {'id': config.segment_sentence_id,
                             'label': config.segment_sentence_label,
                             'region_var': config.segment_sentence_region_var,
                             'priority': config.segment_sentence_priority},
                'supervision': {'id': config.segment_supervision_id,
                                'label': config.segment_supervision_label,
                                'region_var': config.segment_supervision_region_var,
                                'priority': config.segment_supervision_priority},
                'demographic': {'id': config.segment_demographic_id,
                                'label': config.segment_demographic_label,
                                'region_var': config.segment_demographic_region_var,
                                'priority': config.segment_demographic_priority},
                'prosecution': {'id': config.segment_prosecution_id,
                                'label': config.segment_prosecution_label,
                                'region_var': config.segment_prosecution_region_var,
                                'priority': config.segment_prosecution_priority},
                }

db_info = { 
    'stand' : {
            'name' : config.db_stand_name,
            'dir'   : os.path.join(config.meta_dir, 'database', 'standardized'),
            'user'  : config.db_stand_user,
            'pass'  : config.db_stand_pass,
            'collate' : config.db_stand_collate,
            'encoding' : config.db_stand_encoding
            },
    'recid' : {
            'name' : config.db_recid_name,
            'dir'   : os.path.join(config.meta_dir, 'database', 'recidivism'),
            'user'  : config.db_recid_user,
            'pass'  : config.db_recid_pass,
            'collate' : config.db_recid_collate,
            'encoding' : config.db_recid_encoding,
            },
    'subject' : {
            'name' : config.db_subject_name,
            'dir'   : config.db_subject_dir,
            'user'  : config.db_subject_user,
            'pass'  : config.db_subject_pass,
            'collate' : config.db_subject_collate,
            'encoding' : config.db_subject_encoding,
            },
}