#!/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 sys
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))
