import logging
from tempfile import mkdtemp
from shutil import rmtree
from typing import List
import os.path
import json
import yaml

from configerus.config import Config
from configerus.contrib.env import PLUGIN_ID_SOURCE_ENV_SPECIFIC
from configerus.contrib.dict import PLUGIN_ID_SOURCE_DICT
from configerus.contrib.files import PLUGIN_ID_SOURCE_PATH

logger = logging.getLogger('configerus:tests')

TEST_CONFIG_TEMP_DIR = ''
""" on first use, we will populate this with a str path to a parent tmp dir that
    will contain any file config that we use """


def make_test_config(config: Config, sources: List):
    """ Make config of various types from a list, and add it to a config object """
    global TEST_CONFIG_TEMP_DIR

    logger.info("Building sources from source list")
    for source in sources:
        name = source["name"]
        priority = source["priority"] if "priority" in source else config.default_priority()
        type = source["type"]
        data = source["data"]

        if type == PLUGIN_ID_SOURCE_DICT:
            logger.info("Adding 'dict' source '%s' [%s]: %s", name, priority, data.keys())
            config.add_source(type, name, priority).set_data(data)

        elif type == PLUGIN_ID_SOURCE_PATH:
            # on first use, get a temp dir
            if not TEST_CONFIG_TEMP_DIR:
                TEST_CONFIG_TEMP_DIR = mkdtemp()

            # first make files for all of the data
            path = name
            full_path = os.path.join(TEST_CONFIG_TEMP_DIR, path)
            os.makedirs(full_path)
            for file_name, file_data in data.items():
                full_file = os.path.join(full_path, file_name)
                logger.debug("path source '%s' writing file '%s' : %s", name, full_file, file_data)
                with open(full_file, 'w') as config_file_pointer:
                    extension = os.path.splitext(file_name)[1].lower()[1:]
                    if extension == "json":
                        json.dump(file_data, config_file_pointer)
                    elif extension == "yaml" or extension == "yml":
                        yaml.dump(file_data, config_file_pointer)

            # then add the created paths to the config sources
            logger.info("Adding 'path' source '%s' [%s]: %s : %s", name, priority, path, data.keys())
            config.add_source(type, name, priority).set_path(full_path)

        if type == PLUGIN_ID_SOURCE_ENV_SPECIFIC:
            # we can do env plugins as well
            logger.info("Adding 'env' source '%s' [%s]: %s", name, priority, data.keys())
            for env_key, env_data in data.items():
                env_name = "{}_{}".format('CONFIGERUSTEST', env_key).upper()
                logger.info("Adding environment variable : {}".format(env_name))
                os.environ[env_name] = str(env_data)
            config.add_source(type, name, priority).set_base('CONFIGERUSTEST')


def test_config_cleanup(config: Config):
    """ clean up any created temporary folder created """
    if TEST_CONFIG_TEMP_DIR:
        rmtree(TEST_CONFIG_TEMP_DIR)
