/*
 * Filename: ListRequest.java
 *
 * Author: Joe Wang
 *
 * Copyright (c) 2003-2005 
 * The Trustees of Columbia University in the City of New York
 * Columbia University Information Technology
 *
 * This file is part of NINJa.
 *
 * NINJa is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * NINJa is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with NINJa; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */

package edu.columbia.print.ninja.core.service;

import edu.columbia.print.ninja.core.service.ListRequest.Job;
import net.jini.core.event.*;
import net.jini.print.data.Doc;
import net.jini.print.job.*;
import javax.print.attribute.*;
import java.rmi.*;
import net.jini.print.service.PrintService;
import java.util.*;

/**
 * A DocPrintJob created by the request list.
 * Printing this job will result in a new job in the queue
 * @author Joe Wang <jw168@columbia.edu>
 * @since 1.0
 */
public class ListRequest implements RemoteDocPrintRequest, Comparable, RemoteEventListener, java.io.Serializable {
    private static final long serialVersionUID = -7524590001989865216L;
    
    PrintService ps;
    String name;
    Doc doc;
    transient Timer timer;
    PrintRequestAttributeSet attributes;
    RequestInserter server;
    java.util.Map listeners;
    ListRequest(String name, PrintService ps, RequestInserter server) {
        this.name = name;
        this.ps = ps;
        this.server = server;
        this.listeners = new java.util.HashMap();
    }
    
    public String toString() {return name;}
    public boolean equals(Object other) {
        if(!(other instanceof ListRequest)) return false;
        ListRequest o = (ListRequest )other;
        return name.equals(o.name);
    }
    
    public int hashCode() {return name.hashCode();}
    
    String getName() {return name;}
    void setName(String name) {this.name = name;}
    static void debug(Object i) {com.millipad.util.Debug.print(ListRequest.class, i);}
    
    public int compareTo(Object other) {
        if(!(other instanceof ListRequest)) return -1;
        int me = Integer.parseInt(getName());
        int you = Integer.parseInt(((ListRequest )other).getName());
        return me-you;
    }
    
    public PrintService getPrintService() {
        return ps;
    }
    
    public EventRegistration addEventListener(boolean reportPrintDataSuccess, boolean reportPrintDataFailure, Class[] theCategories, PrintJobAttribute[] theValues, boolean reportPrintJobFinished, RemoteEventListener theListener, MarshalledObject theHandbackObject, long theRequestedLeaseDuration) throws RemoteException {
        listeners.put(theListener, null);
        return null;
    }
    
    public void clearListeners() throws RemoteException {
        listeners.clear();
    }

    public void print() throws PrintRequestException, RemoteException {
        print(Long.MAX_VALUE);
    }
    
    public PrintJobAndLease print(long theRequestedLeaseDuration) throws PrintRequestException, RemoteException {
        try {
            Job job = new Job(this, ps, doc, server);
            synchronized(getClass()) {
                if(timer==null) timer=new Timer();
                timer.schedule(job, 0L);
            }
            return new PrintJobAndLease(job, null);
        }
        catch(Exception e) {
            e.printStackTrace();
            //			jobSet.add(JobState.ABORTED);
        }
        return null;
    }
    
    public void setAttributes(PrintRequestAttributeSet theAttributes) {attributes = theAttributes;}
    
    //this is copied as it is serialized
    public PrintRequestAttributeSet getAttributes() {return attributes;}
    
    public void setDoc(Doc theDoc) {doc = theDoc;}
    
    public void notify(net.jini.core.event.RemoteEvent remoteEvent) throws net.jini.core.event.UnknownEventException, RemoteException {
        if(remoteEvent instanceof PrintJobEvent) {
            PrintJobEvent event = (PrintJobEvent )remoteEvent;
            try {
                event = new PrintJobEvent(
                event.getPrintService(), 0L, 0L, new MarshalledObject(this), event.getPrintJob(), event.getAttributes()
                );
                for(java.util.Iterator i = listeners.keySet().iterator(); i.hasNext();) {
                    RemoteEventListener l = (RemoteEventListener )i.next();
                    l.notify(event);
                }
            }
            catch(Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    static class Job extends TimerTask implements net.jini.print.job.PrintJob {
        Doc doc;
        PrintRequest req;
        PrintService service;
        RequestInserter inserter;
        Job(PrintRequest req, PrintService service, Doc doc, RequestInserter inserter) {
            this.req = req;
            this.service = service;
            this.doc = doc;
            this.inserter = inserter;
        }
        
        public EventRegistration addEventListener(boolean reportPrintDataSuccess, boolean reportPrintDataFailure, Class[] theCategories, PrintJobAttribute[] theValues, boolean reportPrintJobFinished, RemoteEventListener theListener, MarshalledObject theHandbackObject, long theRequestedLeaseDuration) throws RemoteException {
            return null;
        }
        
        public javax.print.attribute.PrintJobAttributeSet getAttributes() throws RemoteException {
            return null;
        }
        
        public PrintService getPrintService() throws RemoteException {
            return service;
        }
        
        public void run() {
            try {inserter.sendData((ListRequest )req, doc, net.jini.core.lease.Lease.ANY);}
            catch(Exception e) {e.printStackTrace();}
            synchronized(this) {notify();}
        }
        
    }
}

