/*
 * TaminoSpoolRepository.java
 *
 * Created on 21. April 2002, 19:46
 */

package org.apache.james.mailrepository;

/**
 *
 * @author  hch
 */
public class TaminoSpoolRepository extends TaminoMailRepository implements org.apache.james.services.SpoolRepository {
    
    /** Creates a new instance of TaminoSpoolRepository */
    public TaminoSpoolRepository() {
    }
    
    /**
     * Returns the key for an arbitrarily selected mail deposited in this Repository.
     * Useage: SpoolManager calls accept() to see if there are any unprocessed
     * mails in the spool repository.
     */
    public synchronized String accept() {
        getLogger().debug(this.getClass().getName() + ".accept()");
        while (true) {
            try {
                for(java.util.Iterator it = list(); it.hasNext(); ) {
                    
                    String s = it.next().toString();
                    getLogger().debug("Found item " + s + " in spool.");
                    if (lock(s)) {
                        getLogger().debug("accept() has locked: " + s);
                        return s;
                    }
                }
                wait();
            }
            catch (InterruptedException ignored) {
            }
            catch (java.util.ConcurrentModificationException ignoredAlso) {
            }
        }
        
    }
    
    
    /**
     * Returns the key for an arbitrarily select mail depository in this Repositry that
     * is either ready immediately for delivery, or is younger than it's last_updated plus
     * the number of failed attempts times the delay time.
     * Useage: RemoteDeliverySpool calls accept() with some delay and should block until an
     * unprocessed mail is available.
     */
    public synchronized String accept(long delay) {
        getLogger().debug(this.getClass().getName() + ".accept("+delay+")");
        while (true) {
            long youngest = 0;
            for (java.util.Iterator it = list(); it.hasNext(); ) {
                String s = it.next().toString();
                getLogger().debug("Found item " + s + " in spool.");
                if (lock(s)) {
                    getLogger().debug("accept(delay) has locked: "  + s);
                    //We have a lock on this object... let's grab the message
                    //  and see if it's a valid time.
                    org.apache.james.core.MailImpl mail = retrieve(s);
                    if (mail.getState().equals(org.apache.mailet.Mail.ERROR)) {
                        //Test the time...
                        long timeToProcess = delay + mail.getLastUpdated().getTime();
                        if (System.currentTimeMillis() > timeToProcess) {
                            //We're ready to process this again
                            return s;
                        } else {
                            //We're not ready to process this.
                            if (youngest == 0 || youngest > timeToProcess) {
                                //Mark this as the next most likely possible mail to process
                                youngest = timeToProcess;
                            }
                        }
                    } else {
                        //This mail is good to go... return the key
                        return s;
                    }
                }
            }
            //We did not find any... let's wait for a certain amount of time
            try {
                if (youngest == 0) {
                    wait();
                } else {
                    wait(youngest - System.currentTimeMillis());
                }
            } catch (InterruptedException ignored) {
            }
        }
    }
    
}
