import time
import constants
import heat_demand_simulator

from datetime import datetime, timedelta
from typing import List
from heater_instance_interface import HeaterInstanceInterface
from global_outcome import GlobalOutcome
from tasks.task_outcome import TaskOutcome

def realtime_task(global_outcome: GlobalOutcome, heater_instance_interface: HeaterInstanceInterface, start_date: datetime, end_date: datetime, store_db_function):

    one_minute_difference = timedelta(minutes=1)
    actual_date: datetime = start_date
    # Get difference in days between start and end date.
    difference: timedelta = end_date - start_date
    stopped = False

    for i in range(difference.days):

        seed = heater_instance_interface.get_seed()
        heat_demand_per_minute_in_kW_day = heat_demand_simulator.heat_demand_per_minute_in_kW(heat_demand_simulator.heat_demand(seed, actual_date))

        for heat_demand_per_minute in heat_demand_per_minute_in_kW_day:

            required_workload_in_percent = diff = diff_factor = 0.0
            tries = count = 0
            
            if heat_demand_per_minute > 0.0:
                # Calculate percentage of workload for cpu while runtime.
                # example: 1.5 / 0.04 / 100 = 0.375 = 37.5%
                required_workload_in_percent = heat_demand_per_minute / constants.MAX_WORKLOAD_IN_KW_ONE_PERCENT / 100
                try:
                    start_time = time.time()
                    tries, count, diff, diff_factor = heater_instance_interface.run(required_workload_in_percent, 60000)
                    end_time = time.time()
                    runtime = end_time - start_time
                    sleep_time = 60 - runtime
                    if sleep_time > 0:
                        time.sleep(sleep_time)
                except:
                    print()
                    stopped = True
                    break
                global_outcome.update_tries_count(tries, count)
                
            else:
                # If heat demand is 0, just sleep 1 minute and put values of 0 into list, since no heating required
                time.sleep(60)
            actual_heat_generated = diff_factor * heat_demand_per_minute
            actual_date += one_minute_difference
            store_db_function([TaskOutcome(required_workload_in_percent * 100, 60000, tries, count, diff / 1000, diff_factor, actual_date, heat_demand_per_minute, actual_heat_generated, heater_instance_interface.get_host().hostname, heater_instance_interface.get_host().username)])

        if stopped:
            break
