import json
from string import Template

from SKFClient.core.utils.http_config import HttpConfig
from SKFClient.core.utils.config_utils import ConfigError, optional, check_type, check_set_val, check_min_max, check_min, check_str, \
    check_bool, check_dict, check_opt_str, check_log_level
from SKFClient.core.utils.log import log
from SKFClient.core.utils.aws_config import AwsConfig
from SKFClient.core.utils.mqtt_config import MQTTConfig

class Config:
    def __init__(self, aws_config, mqtt_config, http_config, product_id, device_id, protocol_version, log_level):
        self.aws_mqtt_config = aws_config
        self.local_mqtt_config = mqtt_config
        self.http_config = http_config
        self.product_id = product_id
        self.device_id = device_id
        self.protocol_version = protocol_version
        self.log_level = log_level

    @staticmethod
    def from_dict(obj):
        assert isinstance(obj, dict)
        aws_config_dict = check_dict(obj.get("AwsIoTBroker"))
        aws_config = AwsConfig.from_dict(aws_config_dict)
        lora_mqtt_config_dict = check_dict(obj.get("LocalMQTTBroker"))
        lora_mqtt_config = MQTTConfig.from_dict(lora_mqtt_config_dict)
        http_config_dict = check_dict(obj.get("HTTPServer"))
        http_config = HttpConfig.from_dict(http_config_dict)
        log_level = check_log_level(obj.get("logLevel"))
        product_id = check_str(obj.get("productId"))
        device_id = check_str(obj.get("deviceId"))
        protocol_version = check_str(obj.get("protocolVersion"))
        return Config(aws_config, lora_mqtt_config, http_config, product_id, device_id, protocol_version, log_level)

    def to_dict(self):
        result = dict(AwsIoTBroker=self.aws_config.to_dict(), LocalMQTTBroker=self.local_mqtt_config.to_dict(),
                      HTTPServer=self.http_config.to_dict(), productId=self.product_id, deviceId=self.device_id,
                      protocolVersion=self.protocol_version, logLevel=check_log_level(self.log_level))
        return result

    @staticmethod
    def load(global_config, local_config):
        try:
            with open(local_config) as local_file:
                config_values = json.load(local_file)
                with open(global_config) as global_file:
                    data = global_file.read()
                    config = Template(data).safe_substitute(config_values)
                    return Config.from_dict(json.loads(config))
        except ConfigError:
            raise
        except Exception as error:
            log.debug(error, exc_info=True)
            raise ConfigError("Failed to load config from {} {}".format(global_config, local_config))

if __name__ == '__main__':
    config = Config.load("../../../config/settings.json", "../../../config/settings_local.json")
    print(config)
