'''
Created on 17 avr. 2018

@author: olivier.massot
'''
import collections

from cerberus.validator import Validator
import yaml
from yaml.parser import ParserError

from core import constants


CONFIG = {}

_SCHEMA = {
          'repertoire_defaut': {'type': 'string', 'required': True},
          'repertoire_sortie': {'type': 'string', 'required': True},
          'donnees': {
                      'type': 'dict',
                      'schema': {
                                 'dict': {'type': 'dict', 'required': True},
                                 'dt': {'type': 'dict', 'required': True},
                                 'commun': {'type': 'dict', 'required': True},
                                },
                      'required': True
                      },
          'mail': {'type': 'dict',
                   'schema': {
                                'dict': {
                                            'type': 'dict',
                                            'schema': {
                                                       'dest': {'type': 'string', 'required': True},
                                                       'objet': {'type': 'string', 'required': True},
                                                       'texte': {'type': 'string', 'required': True},
                                                       },
                                            'required': True
                                        },
                                'dt':  {
                                            'type': 'dict',
                                            'schema': {
                                                       'dest': {'type': 'string'},
                                                       'objet': {'type': 'string'},
                                                       'texte': {'type': 'string'},
                                                       },
                                            'required': True
                                        }
                             },
                    'required': True
                   },
          'modifiables': {'type': 'list', 'required': True}
         }

class MissingConfigFile(Exception):
    """ Fichier de configuration manquant """
    pass

class InvalidConfigFile(Exception):
    """ Fichier de configuration invalide """
    pass

def deepupdate(d, u):
    for k, v in u.items():
        if isinstance(v, collections.Mapping):
            d[k] = deepupdate(d.get(k, {}), v)
        else:
            d[k] = v
    return d

def load():

    # charge le fichier de configuration de base
    try:
        with open(constants.CONFIG_FILE_PATH, "rb") as f:
            baseconf = yaml.load(f)
    except FileNotFoundError:
        raise MissingConfigFile("Le fichier de configuration '{}' est introuvable".format(constants.CONFIG_FILE_PATH))
    except ParserError as e:
        raise InvalidConfigFile("Le fichier de configuration '{}' comporte des erreurs ({})".format(constants.CONFIG_FILE_PATH, e))

    deepupdate(CONFIG, baseconf)

    # surcharge la config avec la config utilisateur
    try:
        with open(constants.USER_DATA_PATH, "rb") as f:
            userconf = yaml.load(f)
    except FileNotFoundError:
        pass
    except ParserError as e:
        raise InvalidConfigFile("Le fichier de configuration '{}' comporte des erreurs ({})".format(constants.USER_DATA_PATH, e))

    userconf = patch1(userconf)

    userconf = {key: value for key, value in userconf.items() if value}

    deepupdate(CONFIG, userconf)

    # contrôle le schema de la config
    validator = Validator(_SCHEMA, allow_unknown=True)
    if not validator.validate(CONFIG):
        raise InvalidConfigFile("Erreur dans les fichiers de configuration: {}".format(validator.errors))

def get(*keys):
    dataset = dict(CONFIG)
    for key in keys:
        dataset = dataset[key]
    return dataset

def patch1(userconf):
    """ corrige le fichier de données utilisateur entre la verison 1.0 et 1.1 """
    if not "donnees" in userconf:
        userconf = {"donnees": {"commun": userconf}}
    return userconf


if __name__ == "__main__":
    load()
    print(CONFIG)
