package me.km.scheduler;

import java.util.concurrent.ConcurrentLinkedQueue;

public class AsyncWorker {
    private final ConcurrentLinkedQueue<Runnable> tasks = new ConcurrentLinkedQueue<>();
    private final Thread worker;

    public AsyncWorker() {
        worker = new Thread(() -> run());
    }

    public void start() {
        worker.start();
    }

    public void stop() {
        while(worker.isAlive()) {
            synchronized(worker) {
                worker.interrupt();
            }
            try {
                worker.join(100);
            } catch(InterruptedException ex) {
            }
        }
    }

    private void run() {
        while(true) {
            synchronized(worker) {
                try {
                    worker.wait();
                } catch(InterruptedException ex) {
                    return;
                }
            }
            while(true) {
                if(tasks.isEmpty()) {
                    break;
                }
                Runnable r = tasks.poll();
                try {
                    r.run();
                } catch(Exception ex) {
                    System.out.println("A worker task has thrown an exception:");
                    ex.printStackTrace();
                }
            }
        }
    }

    public void add(Runnable r) {
        tasks.add(r);
        synchronized(worker) {
            worker.notify();
        }
    }

    public boolean hasWork() {
        return !tasks.isEmpty();
    }
}
