package org.jfox.ejb.timer;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import javax.ejb.EJBException;
import javax.ejb.Timer;
import javax.ejb.TimerService;

/**
 * only statless session bean & MDB can get TimerService
 *
 * @author <a href="mailto:yangyong@ufsoft.com.cn">Young Yang</a>
 */

public class EJBTimerService implements TimerService {

    /**
     * EJBTimerTasks, use WeakHashMap, when EJBTimerTask un contained by java.util.Timer,
     * it will be automatic removed by GC
     * EJBTimerTask => timer hashCode
     */
    private Map timerTasks = new WeakHashMap();
//  private List timerTasks = new ArrayList();
    private static java.util.Timer timer = new java.util.Timer();

    private String ejbName;

    public EJBTimerService(String ejbName) {
        this.ejbName = ejbName;
    }

    public Timer createTimer(long duration, Serializable info) throws IllegalArgumentException, IllegalStateException, EJBException {
        EJBTimerTask ejbTimerTask = new EJBTimerTask(this, info);
        timer.schedule(ejbTimerTask, duration);
        timerTasks.put(ejbTimerTask, "" + System.identityHashCode(ejbTimerTask.getTimer()));
        return ejbTimerTask.getTimer();
    }

    public Timer createTimer(long initialDuration, long intervalDuration, Serializable info) throws IllegalArgumentException, IllegalStateException, EJBException {
        EJBTimerTask ejbTimerTask = new EJBTimerTask(this, info);
        timer.scheduleAtFixedRate(ejbTimerTask, initialDuration, intervalDuration);
        timerTasks.put(ejbTimerTask, "" + System.identityHashCode(ejbTimerTask.getTimer()));
        return ejbTimerTask.getTimer();
    }

    public Timer createTimer(Date expiration, Serializable info) throws IllegalArgumentException, IllegalStateException, EJBException {
        EJBTimerTask ejbTimerTask = new EJBTimerTask(this, info);
        timer.schedule(ejbTimerTask, expiration);
        timerTasks.put(ejbTimerTask, "" + System.identityHashCode(ejbTimerTask.getTimer()));
        return ejbTimerTask.getTimer();
    }

    public Timer createTimer(Date initialExpiration, long intervalDuration, Serializable info) throws IllegalArgumentException, IllegalStateException, EJBException {
        EJBTimerTask ejbTimerTask = new EJBTimerTask(this, info);
        timer.scheduleAtFixedRate(ejbTimerTask, initialExpiration, intervalDuration);
        timerTasks.put(ejbTimerTask, "" + System.identityHashCode(ejbTimerTask.getTimer()));
        return ejbTimerTask.getTimer();
    }

    public synchronized Collection getTimers() throws IllegalStateException, EJBException {
        List timers = new ArrayList(timerTasks.size());
        for(Iterator it = timerTasks.keySet().iterator(); it.hasNext();) {
            timers.add(((EJBTimerTask) it.next()).getTimer());
        }
        return Collections.unmodifiableList(timers);
    }

    /**
     * return current EnterpriseBean
     *
     * @return
     */
    public String getEjbName() {
        return ejbName;
    }

    public boolean cancel(EJBTimerTask ejbTimerTask) {
        return timerTasks.remove(ejbTimerTask) != null;
    }

    /**
     * used by TimerHandle.getTimer
     *
     * @param timerIdentity may use Timer.hashCode as TimerIdentity
     * @return
     */
    public Timer getTimer(String timerIdentity) {
        for(Iterator it = timerTasks.entrySet().iterator(); it.hasNext();) {
            Map.Entry entry = (Map.Entry) it.next();
            if(entry.getValue().equals(timerIdentity)) {
                return ((EJBTimerTask) entry.getKey()).getTimer();
            }
        }
        return null;
    }

    public static void main(String[] args) {

    }

}

