/*
 *  @author Ranides Atterwim <ranides@gmail.com>
 *  @copyright Ranides Atterwim
 *  @license WTFPL
 *  @url http://ranides.net/projects/assira
 */

package net.ranides.assira.time;
import java.util.TimerTask;
import javax.swing.SwingUtilities;

/**
 *
 * @author ranides
 * @todo (migration) assira
 */
public abstract class AutoTimerTask<T> {

    /*package*/ TimerTask handle;
    /*package*/ T param;

    public abstract void run(T param, int now, int max);
    
    public AutoTimerTask<T> cancel() {
        if(handle != null) {
            handle.cancel(); 
            handle = null;
        }
        return this;
    }
    
    public boolean active() {
        return handle != null;
    }
    
    protected AutoTimerTask<T> apply(boolean sync, int steps, T param) {
        this.handle =  sync ? new AwtHandler<>(this, steps) : new TaskHandler<>(this, steps);
        this.param = param;
        return this;
    }
    
    protected AutoTimerTask<T> schedule(int delay) {
        TimeUtils.Li.TIMER.schedule( handle, 0, delay );
        return this;
    }
    
    
    
    private static class AwtHandler<Q> extends TaskHandler<Q> {

        public AwtHandler(AutoTimerTask<Q> action, int max) {
            super(action, max);
        }
        
        private final Runnable runner = new Runnable() {
            @Override
            public void run() {
                AwtHandler.super.run();
            }
        };
        
        @Override
        public void run() {
            SwingUtilities.invokeLater(runner);
        }
    }
    
    private static class TaskHandler<Q> extends TimerTask {
        
        private final AutoTimerTask<Q> action;
        private final int max;
        private int now;
        

        public TaskHandler(AutoTimerTask<Q> action, int max) {
            this.action = action;
            this.now = 0;
            this.max = max;
        }

        @Override
        public void run() {
            if (now >= max) {
                if (action instanceof AutoTimerFrame) {
                    ((AutoTimerFrame<Q>)action).finished(action.param);
                }
                cancel();
            } else {
                if (0 == now && action instanceof AutoTimerFrame) {
                    ((AutoTimerFrame<Q>) action).started(action.param);
                } else {
                    action.run(action.param, now, max);
                }
                now++;
            }
        }
    }
}