package me.km.scheduler;

import java.util.LinkedList;

public class AsyncWorker
{
    private final LinkedList<Runnable> tasks = new LinkedList<>();
    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)
                {
                    break;
                }
            }
            
            while(true)
            {
                Runnable r;
                synchronized(tasks)
                {
                    if(tasks.isEmpty())
                    {
                        break;
                    }
                    r = tasks.removeFirst();
                }
                try
                {
                    r.run();
                }
                catch(Exception ex)
                {
                    System.out.println("A worker task has thrown an exception:");
                    ex.printStackTrace();
                }
            }
        }
    }
    
    public void add(Runnable r)
    {
        synchronized(tasks)
        {
            tasks.add(r);
        }
    }
    
    public void doWork()
    {
        synchronized(worker)
        {
            worker.notify();
        }
    }
    
    public boolean hasWork()
    {
        synchronized(tasks)
        {
            return !tasks.isEmpty();
        }
    }
}
