#!/usr/bin/env python3
# Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.

import threading
from threading import Thread
import traceback


# A thread that is given a list of jobs. The thread will repeatedly take a job
# from the list of jobs (which is shared with other threads) and execute it
# until there is no more jobs.
#
# If stop_on_first_failure is True, then the thread will exit upon the first
# failing job. The thread will then clear the jobs to ensure that all other
# workers will also terminate after completing there current job.
#
# Each job is a lambda that takes the worker_id as an argument. To guarantee
# termination each job must itself terminate (i.e., each job is responsible for
# setting an appropriate timeout).
class WorkerThread(Thread):

    # The initialization of a WorkerThread is never run concurrently with the
    # initialization of other WorkerThreads.
    def __init__(self, jobs, jobs_lock, stop_on_first_failure, worker_id):
        Thread.__init__(self)
        self.completed = False
        self.jobs = jobs
        self.jobs_lock = jobs_lock
        self.number_of_jobs = len(jobs)
        self.stop_on_first_failure = stop_on_first_failure
        self.success = True
        self.worker_id = worker_id

    def run(self):
        print_thread("Starting worker", self.worker_id)
        while True:
            (job, job_id) = self.take_job(self.jobs, self.jobs_lock)
            if job is None:
                break
            try:
                print_thread(
                    "Starting job %s/%s" % (job_id, self.number_of_jobs),
                    self.worker_id)
                exit_code = job(self.worker_id)
                print_thread(
                    "Job %s finished with exit code %s" % (job_id, exit_code),
                    self.worker_id)
                if exit_code:
                    self.success = False
                    if self.stop_on_first_failure:
                        self.clear_jobs(self.jobs, self.jobs_lock)
                        break
            except:
                print_thread("Job %s crashed" % job_id, self.worker_id)
                print_thread(traceback.format_exc(), self.worker_id)
                self.success = False
                if self.stop_on_first_failure:
                    self.clear_jobs(self.jobs, self.jobs_lock)
                    break
        print_thread("Exiting", self.worker_id)
        self.completed = True

    def take_job(self, jobs, jobs_lock):
        jobs_lock.acquire()
        job_id = self.number_of_jobs - len(jobs) + 1
        job = jobs.pop(0) if jobs else None
        jobs_lock.release()
        return (job, job_id)

    def clear_jobs(self, jobs, jobs_lock):
        jobs_lock.acquire()
        jobs.clear()
        jobs_lock.release()


def run_in_parallel(jobs, number_of_workers, stop_on_first_failure):
    assert number_of_workers > 0
    if number_of_workers > len(jobs):
        number_of_workers = len(jobs)
    if number_of_workers == 1:
        return run_in_sequence(jobs, stop_on_first_failure)
    jobs_lock = threading.Lock()
    threads = []
    for worker_id in range(1, number_of_workers + 1):
        threads.append(
            WorkerThread(jobs, jobs_lock, stop_on_first_failure, worker_id))
    for thread in threads:
        thread.start()
    for thread in threads:
        thread.join()
    for thread in threads:
        if not thread.completed or not thread.success:
            return 1
    return 0


def run_in_sequence(jobs, stop_on_first_failure):
    combined_exit_code = 0
    worker_id = None
    for job in jobs:
        try:
            exit_code = job(worker_id)
            if exit_code:
                combined_exit_code = exit_code
                if stop_on_first_failure:
                    break
        except:
            print(traceback.format_exc())
            combined_exit_code = 1
            if stop_on_first_failure:
                break
    return combined_exit_code


def print_thread(msg, worker_id):
    if worker_id is None:
        print(msg)
    else:
        for line in msg.splitlines():
            print('WORKER %s: %s' % (worker_id, line))
