from pathlib import Path
from lib.filesystemfinder import FileSystemFinder
from lib.filesystemupdater import FileSystemUpdater

class FileSystemManager:

    def __init__(self, max_hyperperiod, nbr_tasks):
        # Create base structure
        base_path = '../data/'
        Path(base_path).mkdir(parents=True, exist_ok=True)
        base_path += 'tasksets/'
        Path(base_path).mkdir(parents=True, exist_ok=True)
        base_path += 'hyperperiod{}-nbrtasks{}/'.format(max_hyperperiod, nbr_tasks)
        Path(base_path).mkdir(parents=True, exist_ok=True)
        self.finder = FileSystemFinder(max_hyperperiod, nbr_tasks)
        self.updater = FileSystemUpdater(max_hyperperiod, nbr_tasks)

    # Loads all the tasksets with the given hash_codes and returns them as a list
    # if hash_codes has been emitted: Return all tasksets
    def load_tasksets(self, hash_codes=None):
        return self.finder.get_all_tasksets(hash_codes)

    # Saves the tasksets in the given folder structure
    # Tasksets argument could be one or more tasksets
    def save_tasksets(self, tasksets):
        # If list is empty, stop
        assert tasksets, "No tasksets to save"
        self.updater.save_tasksets(tasksets)

    # Collect all tasksets which HAVE NOT BEEN solved (failed tasksets)
    def get_all_not_solved(self):
        return self.finder.get_all_not_solved()

    # Collect all tasksets which HAVE NOT BEEN solved (failed tasksets)
    def get_all_not_yet_solved(self):
        return self.finder.get_all_not_yet_solved()

    # Collect all tasksets which HAVE BEEN solved (Successful tasksets)
    def get_all_solved(self):
        return self.finder.get_all_solved()

    # Collect all tasksets which HAVE been solved within the given time
    def get_all_solved_time(self, max_time):
        return self.finder.get_all_max_time_solved(max_time)

    # Collect all tasksets which HAVE NOT been solved within the given time
    def get_all_not_solved_time(self, max_time):
        return self.finder.get_all_max_time_not_solved(max_time)

    # Return the upper-approximated entropy for each of the tasksets in tasksets
    # Tasksets argument could be one or more tasksets
    def get_all_results(self, tasksets=None):
        return self.finder.get_all_results(tasksets)

    # Return the number of tasksets existing of the given type
    def get_nbr_tasksets(self):
        return self.finder.get_nbr_tasksets()

    # Return the number of tasksets existing of the given type
    def get_nbr_unsolved_tasksets(self):
        return self.finder.get_nbr_unsolved_tasksets()

    # Save all the results acquired from the constraint optimization algorithm.
    # tasksets and solutions arguments could be single arguments or multiple
    def save_timing_results(self, tasksets, time, solutions):
        self.updater.save_timing_results(tasksets, time, solutions)

    # Returns whether this taskset has a solution or not, 
    def is_solved(self, ts):
        return self.finder.is_solved(ts)