class SolutionWriter:
    def __init__(self, soln_file):
        self.w = open(soln_file, 'wt')
        self.wcsv = csv.writer(self.w)
        self.wcsv.writerow(['ToyId', 'ElfId', 'StartTime', 'Duration'])
        self.ref_time = datetime.datetime(2014, 1, 1, 0, 0)
        self.hours = Hours()

    def write(self, toy, elf, work_start_time, work_duration):
        time_string = self.hours.get_time_string(work_start_time)
        self.wcsv.writerow([toy.id, elf.id, time_string, work_duration])

    def close(self):
        self.w.close()
def solution(toy_file, soln_file, num_elves, TARGET):
    """ Creates a simple solution where the next available elf is assigned a toy. Elves do not start
    work outside of sanctioned hours.
    :param toy_file: filename for toys file (input)
    :param soln_file: filename for solution file (output)
    :param myelves: list of elves in a priority queue ordered by next available time
    :return:
    """
    hrs = Hours()

    toy_loader = ToyLoader(toy_file)
    solution_writer = SolutionWriter(soln_file)
    busy_elves_heap = BusyElvesHeap(num_elves)

    elves_ready = ElvesReady()
    scheduler = Scheduler(TARGET, num_elves)

    start = time.time()

    current_time = 497340

    print("Getting initial toys")
    print('time taken = {0}, current_time = {1}'.format(time.time() - start, hrs.get_time_string(current_time)))
    new_toy_orders = toy_loader.get_toys_up_to_minute(current_time)

    print("Loading initial toys into backlog")
    print('time taken = {0}, current_time = {1}'.format(time.time() - start, hrs.get_time_string(current_time)))
    toy_backlog = ToyBacklogV2(new_toy_orders)

    print("Finished initializing toys into backlog")
    print('time taken = {0}, current_time = {1}'.format(time.time() - start, hrs.get_time_string(current_time)))

    toys_finished = 0

    toys_left_at_end = []

    time_of_last_toy_assigned = current_time

    while not (toy_loader.done() and toy_backlog.done() and len(toys_left_at_end) == 0):

        # step 1 process newly arrived toys and fresh elves
        new_elves = busy_elves_heap.get_elves_for_min(current_time)

        elves_ready.add_elves(new_elves)

        if (current_time % 120 == 60):
            print('time taken = {0}, current_time = {1}'.format(time.time() - start, hrs.get_time_string(current_time)))
            print('easy_toys:{0},\t constant_toys:{1},\t variable_toys:{2},\t hardest_toys:{3},\t toys_left_at_end:{4}'.format(
                toy_backlog.easy_toy_list.size, len(toy_backlog.constant_rating_list),
                len(toy_backlog.variable_toy_list), len(toy_backlog.hardest_toy_list), len(toys_left_at_end)))
            print('elves ready:{0}, high-perf-elves:{1}'.format(len(elves_ready.training_elf_list),
                                                                len(elves_ready.high_performance_elf_list)))
            print('toys finished = {0}'.format(toys_finished))

        if (len(elves_ready.training_elf_list) + len(elves_ready.high_performance_elf_list)) == 0:
            current_time = hrs.next_sanctioned_minute(current_time)
            continue

        if (toy_loader.done() and current_time - time_of_last_toy_assigned > 2880 and len(elves_ready.training_elf_list) == num_elves and len(toys_left_at_end) == 0):
            print("starting cleanup")
            for toy in toy_backlog.easy_toy_list.all_toys():
                toys_left_at_end.append(toy)
            toy_backlog.easy_toy_list.clear()
            for toy in toy_backlog.constant_rating_list:
                toys_left_at_end.append(toy)
            toy_backlog.constant_rating_list = []
            while len(toy_backlog.variable_toy_list) > 0:
                toys_left_at_end.append(toy_backlog.pop_variable_toy())
            while len(toy_backlog.hardest_toy_list) > 0:
                toys_left_at_end.append(toy_backlog.pop_hardest_toy())

        if (toy_loader.done() and len(toys_left_at_end) > 0):
            # clean up last toys
            toys_finished += scheduler.clean_up(toys_left_at_end, elves_ready, busy_elves_heap, current_time, solution_writer)

        else:
            # step 2 pair off as many elves and toys as possible
            toys_newly_finished = scheduler.schedule(toy_backlog, elves_ready, busy_elves_heap, current_time,
                                                solution_writer, toy_loader)
            toys_finished += toys_newly_finished
            if (toys_newly_finished > 0):
                time_of_last_toy_assigned = current_time

        current_time = hrs.next_sanctioned_minute(current_time)

    toy_loader.close()
    solution_writer.close()