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 daily_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):

        outcome_list:List[TaskOutcome] = []

        seed:int = 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, constants.DAILY_MODE_MILLISECONDS_MINUTE_RATIO)
                    end_time = time.time()
                    runtime = end_time - start_time
                    sleep_time = 0.06 - runtime
                    if sleep_time > 0:
                        time.sleep(sleep_time)
                except:
                    print()
                    stopped = True
                    break
                global_outcome.update_tries_count(tries, count)
            
            else:
                time.sleep(0.06)

            actual_heat_generated = diff_factor * heat_demand_per_minute
            outcome_list.append(TaskOutcome(required_workload_in_percent, constants.DAILY_MODE_MILLISECONDS_MINUTE_RATIO, 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))
            actual_date += one_minute_difference

        if stopped:
            break

        store_db_function(outcome_list)
