/* Copyright (c) 2008 Charles Rich and Worcester Polytechnic Institute.
 * All Rights Reserved.  Use is subject to license terms.  See the file
 * "license.terms" for information on usage and redistribution of this
 * file and for a DISCLAIMER OF ALL WARRANTIES.
 */
package edu.wpi.cetask;

import org.w3c.dom.Node;

import javax.script.*;

public class Script extends Description implements Description.Taskable {
   
   private final TaskClass task;
   public TaskClass getTask () { return task; } // Taskable
   
   private final String script, applicable; 
   private final CompiledScript compiledScript, compiledApplicable;
   
   public Boolean isApplicable (Task occurrence) {
      return occurrence.evalCondition(applicable, compiledApplicable, 
            task+" applicable");
   }
      
   Script (Node node, TaskEngine engine, TaskClass task) {
      super(node, engine);
      if ( task == null ) {
         String qname = xpath("./@task");
         if ( qname.length() > 0 ) task = resolveTaskClass(qname);
      }
      this.task = task;
      String where = task == null ? getModel() : task.toString();
      String app = xpath("./@applicable");
      if ( TaskEngine.COMPILABLE ) {
         compiledScript = engine.compile(getText(), where);
         compiledApplicable = engine.compile(app, where+" applicable");
         script = applicable = null; 
      } else {
         script = getText(); applicable = app; 
         compiledScript = compiledApplicable = null;
      }
   }
     
   public String getModel () {
      return Utils.emptyNull(xpath("./@model"));
   }
   
   public String getPlatform () {
      return Utils.emptyNull(xpath("./@platform"));
   }
   
   public String getDeviceType () {
      return Utils.emptyNull(xpath("./@deviceType"));
   }
   
   public boolean isInit () {
      return Boolean.parseBoolean(xpath("./@init"));
   }
   
   public String getText () { return xpath("."); }

   public void eval (Task occurrence) {
      if ( TaskEngine.COMPILABLE ) {
         if ( compiledScript == null ) return;
         // assuming that $platform and $deviceType already in task.bindings
         try { 
            occurrence.bindings.put(ScriptEngine.FILENAME, task.toString());
            compiledScript.eval(occurrence.bindings);
         } 
         catch (ScriptException e) { throw new RuntimeException(e); }
         finally { occurrence.bindings.remove(ScriptEngine.FILENAME); } 
      } else engine.eval(script, occurrence.bindings, task.toString()); 
   }
}

