__author__ = "Christian Kongsgaard"
__license__ = "MIT"

# -------------------------------------------------------------------------------------------------------------------- #
# IMPORTS

# Modules:
import os
import yaml
import numpy as np

# RiBuild Modules:
from delphin_6_automation.database_interactions.db_templates import delphin_entry as delphin_db, delphin_entry
from delphin_6_automation.database_interactions.db_templates import result_raw_entry as result_db
from delphin_6_automation.database_interactions.db_templates import weather_entry as weather_db
from delphin_6_automation.database_interactions.db_templates import material_entry as material_db
from delphin_6_automation.database_interactions import delphin_interactions
from delphin_6_automation.database_interactions import material_interactions
from delphin_6_automation.database_interactions import weather_interactions
from delphin_6_automation.logging.ribuild_logger import ribuild_logger

# Logger
logger = ribuild_logger()


# -------------------------------------------------------------------------------------------------------------------- #
# MATERIAL INTERACTIONS


def download_raw_result(result_id: str, download_path: str) -> bool:
    """
    Downloads a result entry from the database.rst.

    :param result_id: Database entry id
    :param download_path: Path where the result should be written
    :return: True
    """

    result_obj = result_db.Result.objects(id=result_id).first()
    download_path = os.path.join(download_path, str(result_id))

    if not os.path.exists(download_path):
        os.mkdir(download_path)

    # delphin_parser.write_log_files(result_obj, download_path)
    delphin_interactions.download_result_files(result_obj, download_path)

    return True


def queue_priorities(priority: str) -> int:
    """
    Generate a queue priority number.

    :param priority: High, medium or low priority
    :return: Priority number
    """

    priority_list = [obj.queue_priority
                     for obj in delphin_db.Delphin.objects.order_by('queue_priority')]

    if not priority_list:
        return 1

    else:
        min_priority = min(priority_list)
        max_priority = max(priority_list)
        span = max_priority - min_priority

        if priority == 'high':
            priority_number = int(max_priority)

        elif priority == 'medium':
            priority_number = int(span + 0.5 * min_priority)

        elif priority == 'low':
            priority_number = int(span + 0.25 * min_priority)

        else:
            raise ValueError('priority has to be: high, medium or low. Value given was: ' + str(priority))

        return priority_number


def add_to_simulation_queue(delphin_file: str, priority: str) -> str:
    """
    Uploads and adds a Delphin project file to the simulation queue.

    :param delphin_file: Delphin 6 project file path
    :param priority: High, medium or low priority
    :return: Database entry id
    """

    priority_number = queue_priorities(priority)
    simulation_id = delphin_interactions.upload_delphin_to_database(delphin_file, priority_number)

    logger.debug(f'Added Delphin project with ID: {simulation_id} to queue with priority: {priority}')

    return simulation_id


def is_simulation_finished(sim_id: str) -> bool:
    """
    Checks if a Delphin project entry is simulated or not.

    :param sim_id: Database entry to check
    :return: True if it is simulated otherwise returns False.