import os
import logging
import yaml
from schema import Use, Schema, SchemaError, Optional


class InvalidConfig(Exception):
    pass


class MissingConfig(Exception):
    pass


default_config = {
    'logging': 30,
    'migrate_from_0_3_2': True
}
schema = Schema({
    'stellar_url': Use(str),
    'url': Use(str),
    'project_name': Use(str),
    'tracked_databases': [Use(str)],
    Optional('logging'): int,
    Optional('migrate_from_0_3_2'): bool
})


def get_config_path():
    current_directory = os.getcwd()
    while True:
        try:
            with open(
                os.path.join(current_directory, 'stellar.yaml'),
                'rb'
            ) as fp:
                return os.path.join(current_directory, 'stellar.yaml')
        except IOError:
            pass

        current_directory = os.path.abspath(
            os.path.join(current_directory, '..')
        )
        if current_directory == '/':
            return None


def load_config():
    config = {}
    stellar_config_env = os.getenv('STELLAR_CONFIG')
    if stellar_config_env:
        if os.path.exists(stellar_config_env):
            config = yaml.safe_load(open(stellar_config_env))
    else:
        current_directory = os.getcwd()
        while True:
            try:
                with open(
                    os.path.join(current_directory, 'stellar.yaml'),
                    'rb'
                ) as fp:
                    config = yaml.safe_load(fp)
                    break
            except IOError:
                pass

            if current_directory == '/':
                break

            current_directory = os.path.abspath(
                os.path.join(current_directory, '..')
            )

    if not config:
        raise MissingConfig()

    for k, v in default_config.items():
        if k not in config:
            config[k] = v

    try:
        return schema.validate(config)
    except SchemaError as e:
        raise InvalidConfig(e)


def save_config(config):
    logging.getLogger(__name__).debug('save_config()')
    with open(get_config_path(), "w") as fp:
        yaml.dump(config, fp)

[(30, 'os.getcwd', 'os.getcwd', ([], {}), False, 'import os\n'), (50, 'os.getenv', 'os.getenv', (['"""STELLAR_CONFIG"""'], {}), False, 'import os\n'), (24, 'schema.Optional', 'Optional', (['"""logging"""'], {}), False, 'from schema import Use, Schema, SchemaError, Optional\n'), (25, 'schema.Optional', 'Optional', (['"""migrate_from_0_3_2"""'], {}), False, 'from schema import Use, Schema, SchemaError, Optional\n'), (20, 'schema.Use', 'Use', (['str'], {}), False, 'from schema import Use, Schema, SchemaError, Optional\n'), (21, 'schema.Use', 'Use', (['str'], {}), False, 'from schema import Use, Schema, SchemaError, Optional\n'), (22, 'schema.Use', 'Use', (['str'], {}), False, 'from schema import Use, Schema, SchemaError, Optional\n'), (52, 'os.path.exists', 'os.path.exists', (['stellar_config_env'], {}), False, 'import os\n'), (55, 'os.getcwd', 'os.getcwd', ([], {}), False, 'import os\n'), (90, 'yaml.dump', 'yaml.dump', (['config', 'fp'], {}), False, 'import yaml\n'), (23, 'schema.Use', 'Use', (['str'], {}), False, 'from schema import Use, Schema, SchemaError, Optional\n'), (42, 'os.path.join', 'os.path.join', (['current_directory', '""".."""'], {}), False, 'import os\n'), (88, 'logging.getLogger', 'logging.getLogger', (['__name__'], {}), False, 'import logging\n'), (37, 'os.path.join', 'os.path.join', (['current_directory', '"""stellar.yaml"""'], {}), False, 'import os\n'), (71, 'os.path.join', 'os.path.join', (['current_directory', '""".."""'], {}), False, 'import os\n'), (34, 'os.path.join', 'os.path.join', (['current_directory', '"""stellar.yaml"""'], {}), False, 'import os\n'), (62, 'yaml.safe_load', 'yaml.safe_load', (['fp'], {}), False, 'import yaml\n'), (59, 'os.path.join', 'os.path.join', (['current_directory', '"""stellar.yaml"""'], {}), False, 'import os\n')]