/*
 * Filename: SpoolIntercept.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.prix.requester;

import edu.columbia.print.*;
import java.util.*;
import java.io.*;
import com.millipad.util.*;
import javax.print.*;
import javax.print.attribute.*;
import javax.print.attribute.standard.*;

//we can get jobs from windows & unix machines,
//but we can only send jobs to other windows machines because they are emf/spl files
public class SpoolIntercept extends Requester {

	Set pollers;
	Set children;
	Set inUse;
	BlockingStack stack, dirStack;

	public SpoolIntercept(String requester) throws Exception {
		pollers = new HashSet();
		children = new HashSet();
		inUse = new HashSet();
		stack = new BlockingStack(1);
                dirStack = new BlockingStack();
                new DirectoryFetch(dirStack).start();

		ResourceBundle bundle = ResourceBundle.getBundle(
			getClass().getPackage().getName()+".resource"
			);
		StringTokenizer t = new StringTokenizer(requester);
                System.out.println("spoolIntercept: "+requester);
		for(; t.hasMoreTokens();) {
			Requester req = (Requester )Class.forName(t.nextToken()).newInstance();
                        children.add(req);
			}
		}

        public void setInputDevice(String id) {
            for(Iterator i=children.iterator(); i.hasNext();) {
                Requester req = (Requester )i.next();
                req.setInputDevice(id);
            }
        }

        public int produceRequest(File in, PrintRequestAttributeSet attr, Class[] required, BlockingStack result) throws IOException {
            dirStack.push(new Object[] {in, attr, required, new Long(0)});
            return REQUEST_DISPATCHED;
		}

	public void addPrintService(net.jini.print.service.PrintService l) {
		if(l==null) return;
		for(Iterator i=children.iterator(); i.hasNext();) {
			((Requester )i.next()).addPrintService(l);
			}
		}

	void debug(Object in) {Debug.print(SpoolIntercept.class, in);}

        class DirectoryFetch extends Thread {
            BlockingStack stack;
            final BlockingStack result = new BlockingStack();
            final Set set = new HashSet();
            DirectoryFetch(BlockingStack stack) {
                this.stack = stack;
                new Thread() {
                    public void run() {
                        for(;;) {
                            File file = (File )result.pop();
                            
                            try{file.delete();}
                            catch(Exception e) {
                                System.out.println("delete failed: "+file.getName());
                            }
//                            try {Thread.sleep(500);}
//                            catch(Exception e) {}
                            synchronized(set) {
                                set.remove(file.getAbsolutePath());
//                                System.out.println("-"+file);
                            }
                        }
                    }
                }.start();
            }
            public void run() {
                for(;;) {
                    Object[] params = (Object[] )stack.pop();
                    try {
                        File in = (File )params[0];
                        Long lastMod = (Long )params[3];
/*                        if(lastMod!=null) {
                            if(lastMod.longValue()==in.lastModified()) {
                                Thread.sleep(5000);
                                stack.push(params);
                                continue;
                            }
                            params[3] = new Long(in.lastModified());
                        }
*/                        Class[] required = (Class[] )params[2];
                        File[] files = in.listFiles();
//                        assert files!=null : "IOError in spool directory "+in.getPath();
                        //add files to set
			for(int i = files.length-1; i>=0; i--) {
                            synchronized(set) {
                                if(set.contains(files[i].getAbsolutePath())) continue;
                                set.add(files[i].getAbsolutePath());
                            }
                        }
			for(int i = files.length-1; i>=0; i--) {
                            if(!files[i].exists()) continue;
                            if(files[i].lastModified()+1000>System.currentTimeMillis()) {
                                continue;
                            }
                            PrintRequestAttributeSet attr = new HashPrintRequestAttributeSet();
                            for(Iterator j=children.iterator(); j.hasNext();) {
				Requester req = (Requester )j.next();
				if(req.produceRequest(files[i], attr, required, result)!=REQUEST_DISPATCHED) {
                                    set.remove(files[i].getAbsolutePath());
				}
                            }
			}
                    }
                    catch(Exception e) {
                        e.printStackTrace();
                    }
                    stack.push(params);
                }
            }
        }
}

