package nxm.sys.intr;

import nxm.sys.inc.AsciiMap;
import nxm.sys.lib.Args;
import nxm.sys.lib.Convert;
import nxm.sys.lib.Intrinsic;

/**
  Handles switch functions within macros.

  @author Jeff Schoen
*/
public class Switch extends Intrinsic {

  /** default constructor */
  public Switch () {}

  public int process () {
    String func   = MA.getU("FUNC");
    String name   = MA.getU("NAME");
    String label  = MA.getU("VALUE");
    Object def    = (MA.find("DEF")) ? MA.getO("DEF")  : null;
    Object sdef   = (MA.find("SDEF"))? MA.getO("SDEF") : null;
    String nameAsSwitch = AsciiMap.SLASH+name;
    verbose = !MA.getZ("/QUIET", !verbose); // since 3.3.0: option to override inherited /verbose

    if (func.equals("GET")) {
      MR.put(label,getSwitchValue(nameAsSwitch, def, sdef));
    }
    else if (func.equals("GETALL")) {
      nxm.sys.lib.Table values = Convert.o2t(label,this);
      if (values == null) values = new nxm.sys.lib.Table();

      for (String key : MA.getAllSwitchNames()) {
        String tag = key.substring(1);  // strip off leading '/'
        Object val = getSwitchValue(key, def, sdef);
        values.put(tag, val);
      }
      MR.put(label, values);
    }
    // SET logic added in 2.9.0. and redone in 3.1.3 (BUG 2010)
    else if (func.equals("SET")) {
      if (label!=null) {
        // set to highest prec
        if (M.macro != null && M.macro.lines != null && M.macro.lines[0] != null) {
          // done like this because we still need translations in args.getX below
          M.macro.lines[0].put(nameAsSwitch,label) ;
        }
      }
    }
    // DEL logic added in 2.9.0. and updated in 3.1.3 (BUG 2010)
    else if (func.equals("DEL")) {
      // save the current value, if any, into the results table
      Object val = getSwitchValue(nameAsSwitch, def, sdef);
      MR.put(label, val);

      if (MA.find(nameAsSwitch)) {
        if (verbose && MT != null) M.println("Removing "+name+" from Args table");  // since 3.7.1 using M.println instead of M.terminal.writeln to allow logging - NXM-1813
        MA.remove(nameAsSwitch);
      }
      if (M.macro != null && M.macro.lines != null) {
        if (M.macro.lines[0] != null) {
          if (M.macro.lines[0].find(nameAsSwitch)) {
            if (verbose && MT != null) M.println("INFO: Removing "+nameAsSwitch+" from parent macro line switches");
            M.macro.lines[0].remove(nameAsSwitch);
          }
        }
        if (M.macro.lines[1] != null) {
          if (M.macro.lines[1] != null) {
            if (verbose && MT != null) M.println("INFO: Removing "+nameAsSwitch+" from macro line switches");
            M.macro.lines[1].remove(nameAsSwitch) ;
          }
        }
      }
    }
    else M.warning("Switch func "+func+" not implemented yet");
    return FINISH;
  }

  /** gets the switch value
      @param name Switch name (with a '/' prefix)
      @param def  The default value
      @param sdef The state default value
      @return The switch value
      @since NeXtMidas 2.9.0 (Bug 2284)
   */
  private Object getSwitchValue (String name, Object def, Object sdef) {
    boolean upperCase = MA.getNoState("/CS", true); // since 3.1.2 to support case-sensitive switches for Bug 2583
    Object value = MA.getO(name, null, upperCase);
    if (value == null) return def;

    if (value == Args.STATE_SWITCH_VAL) {  // state switch... uses STATE_SWITCH_VAL since 2.9.0 (Bug 2285)
      if (sdef != null) return sdef;
      if (def  != null) return def;
    }

    return value;
  }

}
