/*
 *
 * ====================================================================
 *
 * Copyright 2004 The Apache Software Foundation 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package org.apache.slide.projector.engine;

import java.util.Iterator;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.contract.Context;
import org.apache.commons.xmlio.out.XMLStringWriter;
import org.apache.commons.xmlio.out.XMLWriter;
import org.apache.slide.projector.Projector;
import org.apache.slide.projector.constraints.ConstraintsManager;
import org.apache.slide.projector.expression.Expression;
import org.apache.slide.projector.value.URI;

public class Job implements Runnable {
    private final static Logger logger = Logger.getLogger(Job.class.getName());

    protected Expression initialCondition, remainingCondition;
    protected Map parameters;
    private URI processorUri;
    private boolean repeat, persistent;
    private String id;
    
    public Job(String id, URI processorUri, Expression initalCondition, Expression remainingCondition, Map parameters, boolean repeat, boolean persistent) {
    	this.id = id;
    	this.initialCondition = initalCondition;
    	this.remainingCondition = remainingCondition;
    	this.parameters = parameters;
    	this.processorUri = processorUri;
    	this.repeat = repeat;
    	this.persistent = persistent;
    }

    public void run() {
        try {
            logger.log(Level.FINE, "Launching scheduled process '"+getProcessorUri()+"'");
            Context context = Projector.getSystemContext();
            Scheduler.setContext(context);
            ProcessorManager.getInstance().process(getProcessorUri(), getParameters(), context);
        } catch ( Exception e ) {
            logger.log(Level.SEVERE, "Scheduled process '"+getProcessorUri()+"' failed", e);
        }
    }

    public Expression getInitialCondition() {
        return initialCondition;
    }

    public Expression getRemainingCondition() {
        return remainingCondition;
    }

    public URI getProcessorUri() {
        return processorUri;
    }

    public Map getParameters() {
        return parameters;
    }

    public boolean repeat() {
        return repeat;
    }

    public boolean isPersistent() {
        return persistent;
    }
    
    public void restart() {
    	remainingCondition = initialCondition;
    }
    
    public void activate() {
    	remainingCondition = remainingCondition.activate(this);
    }
    
    public void save(XMLStringWriter writer) {
    	writer.writeStartTag(XMLWriter.createStartTag("job", new String[] { "id", "processor" }, new String[] { id, ProcessorManager.THREAD.toString() }));
		writer.writeStartTag(XMLWriter.createStartTag("load", "parameter", "parameters"));
		writer.writeStartTag(XMLWriter.createStartTag("map"));
        for ( Iterator i = getParameters().entrySet().iterator(); i.hasNext(); ) {
            Map.Entry entry = (Map.Entry)i.next();
            String key = (String)entry.getKey(); 
            writer.writeStartTag(XMLWriter.createStartTag("entry", new String[][] { {"key", key } }));
            ConstraintsManager.getInstance().saveValue(entry.getValue(), writer);
            writer.writeEndTag(XMLWriter.createEndTag("entry"));
        }
		writer.writeEndTag(XMLWriter.createEndTag("map"));
        writer.writeEndTag(XMLWriter.createEndTag("load"));
		writer.writeStartTag(XMLWriter.createStartTag("load", "parameter", "condition"));
        writer.writeStartTag(XMLWriter.createStartTag("xml"));
        getInitialCondition().save(writer);
        writer.writeEndTag(XMLWriter.createEndTag("xml"));
        writer.writeEndTag(XMLWriter.createEndTag("load"));
        writer.writeStartTag(XMLWriter.createStartTag("load", "parameter", "remainingCondition"));
        writer.writeStartTag(XMLWriter.createStartTag("xml"));
        getRemainingCondition().save(writer);
        writer.writeEndTag(XMLWriter.createEndTag("xml"));
        writer.writeEndTag(XMLWriter.createEndTag("load"));
		writer.writeStartTag(XMLWriter.createStartTag("load", "parameter", "repeat"));
        ConstraintsManager.getInstance().saveValue(new Boolean(repeat), writer);
        writer.writeEndTag(XMLWriter.createEndTag("load"));
		writer.writeStartTag(XMLWriter.createStartTag("load", "parameter", "persistent"));
        ConstraintsManager.getInstance().saveValue(new Boolean(persistent), writer);
        writer.writeEndTag(XMLWriter.createEndTag("load"));
		writer.writeStartTag(XMLWriter.createStartTag("load", "parameter", "processor"));
        ConstraintsManager.getInstance().saveValue(getProcessorUri(), writer);
        writer.writeEndTag(XMLWriter.createEndTag("load"));
        writer.writeEndTag(XMLWriter.createEndTag("job"));
    }

    public void launch() {
        try {
            Thread processThread = new Thread(this);
            processThread.setDaemon(true);
            processThread.start();
        } catch ( Exception exception ) {
            logger.log(Level.SEVERE, "Exception occured while doing job: "+this, exception);
        }
    }
}