from boaviztapi import config
from boaviztapi.model.boattribute import Boattribute
from boaviztapi.model.device import Device
from boaviztapi.model.component import Component
from boaviztapi.model.services.cloud_instance import ServiceCloudInstance, Service


def verbose_cloud(cloud_instance: ServiceCloudInstance, selected_criteria=config["default_criteria"],
                  duration=config["default_duration"]):
    json_output = {**iter_boattribute(cloud_instance),
                   **verbose_usage(cloud_instance),
                   **verbose_device(cloud_instance.platform, selected_criteria=selected_criteria, duration=duration)}
    return json_output


def verbose_device(device: Device, selected_criteria=config["default_criteria"], duration=config["default_duration"]):
    json_output = {"duration": {"value": duration, "unit": "hours"}}
    for component in device.components:
        component.usage.hours_life_time.set_completed(device.usage.hours_life_time.value,
                                                      min=device.usage.hours_life_time.min,
                                                      max=device.usage.hours_life_time.max, source="from device")
        if f"{component.NAME}-1" in json_output:
            i = 2
            while f"{component.NAME}-{i}" in json_output:
                i += 1
            key = f"{component.NAME}-{i}"
        else:
            key = f"{component.NAME}-1"

        json_output[key] = verbose_component(component, selected_criteria, duration)

    json_output = {**json_output, **verbose_usage(device), **iter_boattribute(device)}

    return json_output


def verbose_usage(device: [Device, Component, Service]):
    json_output = {**iter_boattribute(device.usage)}
    if device.usage.consumption_profile is not None:
        if device.usage.consumption_profile.workloads.is_set():
            json_output["workloads"] = device.usage.consumption_profile.workloads.to_json()
            json_output["workloads"]["value"] = [
                {"load_percentage": workload.load_percentage, "power_watt": workload.power_watt} for workload in
                json_output["workloads"]["value"]]
        if device.usage.consumption_profile.params.is_set():
            json_output["params"] = device.usage.consumption_profile.params.to_json()
    for elec in device.usage.elec_factors:
        if device.usage.elec_factors[elec].is_set():
            json_output[f"{elec}_factor"] = device.usage.elec_factors[elec].to_json()

    return json_output


def verbose_component(component: Component, selected_criteria=config["default_criteria"],
                      duration=config["default_duration"]):
    json_output = {"impacts": component.get_impacts(selected_criteria), **iter_boattribute(component),
                   "duration": {"value": duration, "unit": "hours"}}

    if component.usage.avg_power.is_set():
        json_output = {**json_output, **verbose_usage(component)}

    return json_output


def iter_boattribute(element):
    json_output = {}
    for attr, val in element.__iter__():
        if not isinstance(val, Boattribute):
            continue
        if val.is_set():
            json_output[attr] = val.to_json()
    return json_output
