package commons.script;

import java.io.File;
import basics.application.Args;
import basics.application.Config;
import basics.application.user.AppUser;
import basics.application.user.User;
import basics.filesystem.file.FileUtl;
import basics.filesystem.file.LineReader;
import basics.unexpected.Failure;
import basics.utl.Empty;
import basics.utl.SUtl;
import basics.utl.SysUtl;
import commons.application.GLOBAL;
import commons.application.Application;
import commons.application.ctx.Context;
import commons.utl.CtxUtl;

public class ScriptLoader
{
public static final String  IgnoreLine = "#";
private static final String E0         = "Missing script name!";
private static final String E1         = "Missing script %!";
Context                     ctx        = null;
Analyzer                    analyzer   = null;

public ScriptLoader(Analyzer analyzer, Context ctx)
{
   this.ctx = ctx;
   this.analyzer = analyzer;
}

/**
 * Loads a script sends the lines to the pre-compiler
 * that analyzes the line and construct a tree representing the script.
 * The tree representation is in an none evaluated state after this process,
 * which means that values have not been resolved and subscripts are not yet
 * been loaded. Subscript loading is done during execution of the script,
 * so we have a pre-compiled unit of code which dynamically loads sub units. 
 * @param parent
 * @param scriptName
 * @return
 */
public XNode load(XNode parent, String scriptName)
{
   if(Empty.is(scriptName))
      throw new Failure(E0);
   if(!scriptName.toLowerCase().endsWith(GLOBAL.VAL_SCRIPT_SUFFIX))
      scriptName = scriptName + GLOBAL.VAL_SCRIPT_SUFFIX;
   String path = FileUtl.concat(CtxUtl.scriptSpace(ctx).getAbsolutePath(), scriptName);
   LineReader reader = new LineReader(path);
   if(!reader.open())
      throw new Failure(SUtl.sprint(E1, path));
   XNode node = parent;
   int line = 0;
   TokenizedLines lines = new TokenizedLines();
   while(reader.hasLine())
   {
      String input = reader.nextLine();
      if(!Empty.is(input) && !input.startsWith(IgnoreLine))
         lines.add(++line, InputTokenizer.parse(input));
   }
   reader.close();
//   Util.printTokenizedLines(lines);
   node = analyzer.analyzeSyntax(ctx, node, lines);
//   Util.printTree(node);
   return parent;
}

public static void main(String [] args)
{
   unittest();
}

public static void unittest()
{
   Context ctx = new Context();
   Args prgArgs = new Args(new String [] { });
   CtxUtl.addPropertiesToEnv(Application.ctx(), new Config(GLOBAL.KEY_CONFIG_APPLICATION)
      .getProperties());
   ctx.env().put(GLOBAL.CTX_ENVKEY_BASEDIR,
      prgArgs.getOption("basedir", ctx.env().get(GLOBAL.CTX_ENVKEY_BASEDIR, "home")));
   String uid = prgArgs.getOption("userid", ctx.env().consume("userid", "."));
   //   if(!Empty.is(uid))
   ctx.env().put(GLOBAL.CTX_ENVKEY_USER, AppUser.create(uid, null, null, User.ROLE.ADMIN.name()));
   SysUtl.trace("user  : " + ctx.env().get(GLOBAL.CTX_ENVKEY_USER, ""));
   SysUtl.trace("home  : " + new File(CtxUtl.userHome(ctx)).getAbsolutePath());
   Analyzer analyzer = new Analyzer();
   ScriptLoader loader = new ScriptLoader(analyzer, ctx);
   XNode root = new XNode();
   XNode node = loader.load(root, "demo");
   //   InstructionNode node = loader.load(InstructionNode.createRoot(), "demo");
}
}
