package nxm.sys.prim;

import nxm.sys.lib.Convert;
import nxm.sys.lib.Message;
import nxm.sys.lib.Message.XmMsgType;
import nxm.sys.lib.Primitive;
import nxm.sys.lib.StringUtil;
import nxm.sys.lib.Table;
import nxm.sys.libm.Tolerance;

/** Tests messaging functionality when NeXtMidas is run as an X-Midas option tree. This primitive is
    not configured and is only used as part of the confidence tests run from X-Midas.
    @author  J. Czechowski IV
    @since   NeXtMidas 2.1.1
 */
public class testxmmsg extends Primitive {
  private int numTests = 0; // Total number of tests
  private int numFails = 0; // Number of failed tests
  private String xmid = "";
  private String nmid = "";
  private static final String longstr12 = "abcdefghijkl";
  private static final String longstr32 = "abcdefghijklmnopqrstuzwxyz012345";
  private static final String longstr36 = "abcdefghijklmnopqrstuzwxyz0123456789"; // Note: 36 truncated to 32 characters when being sent.

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

  public int open () {
    pollTime = args.getD("/POLL", 0.1); // default to one-tenth second poll time, since nothing is done in process()
//  xmid = getMsgID();       // 2011-03-29 TODO: fix Command.getMsgID() to support "XM.1"
    xmid = MA.get("/MSGID"); // 2011-03-29: workaround for problem with getMsgID() noted in above line
    nmid = "XM." + getID();
    return NORMAL;
  }

  public int processMessage (Message msg) {
    int status = NOOP;

    if (msg.name.equals("TEST1")) {       // Unconfigured message with no data
      Table tbl = Convert.o2t(msg.data);
      doAssert("TEST1 message fid=" + xmid,    (xmid.equals(msg.getFromID())));
      doAssert("TEST1 message to="  + nmid,    (nmid.equals(msg.getToID())));
      doAssert("TEST1 message info=99",        (msg.info   == 99));
      doAssert("TEST1 message data.getsize=0", (tbl.size() == 0));
    }
    else if (msg.name.equals("TEST2")) {  // Unconfigured message with data
      Table tbl = Convert.o2t(msg.data);
      doAssert("TEST2 message fid=" + xmid,    (xmid.equals(msg.getFromID())));
      doAssert("TEST2 message to="  + nmid,    (nmid.equals(msg.getToID())));
      doAssert("TEST2 message info=7",         (msg.info   == 7));
      doAssert("TEST2 message data.getsize=3", (tbl.size() == 3));
      doAssert("TEST2 message val1=1",         (tbl.getD("VAL1") ==  1));
      doAssert("TEST2 message val2=Two",       (tbl.getS("VAL2").equals("Two")));
      doAssert("TEST2 message val3=3",         (tbl.getD("VAL3") ==  3));
    }
    else if (msg.name.equals("TEST3")) {  // Unconfigured message with string
      Table tbl = Convert.o2t(msg.data);
      doAssert("TEST3 message fid=" + xmid,    (xmid.equals(msg.getFromID())));
      doAssert("TEST3 message to="  + nmid,    (nmid.equals(msg.getToID())));
      doAssert("TEST3 message info=0",         (msg.info   == 0));
      doAssert("TEST3 message data.getsize=4", (tbl.size() == 4));
      doAssert("TEST3 message val1=1",         (tbl.getD("VAL1") ==  1));
      doAssert("TEST3 message val2=longstr12", (longstr12.equals(tbl.getS("VAL2"))));
      doAssert("TEST3 message val3=longstr32", (longstr32.equals(tbl.getS("VAL3"))));
      doAssert("TEST3 message val4=2",         (tbl.getD("VAL4") ==  2));
    }
    else if (msg.name.equals("TEST4")) {  // Unconfigured message type multipliers
      Table tbl = Convert.o2t(msg.data);
      doAssert("TEST4 message fid=" + xmid,    (xmid.equals(msg.getFromID())));
      doAssert("TEST4 message to="  + nmid,    (nmid.equals(msg.getToID())));
      doAssert("TEST4 message info=0",         (msg.info   == 0));
      doAssert("TEST4 message data.getsize=6", (tbl.size() == 6));
      doAssert("TEST4 message val1=1",         (tbl.getD("VAL1") ==  1));
      doAssert("TEST4 message val2=2",         (tbl.getD("VAL2") ==  2));
      doAssert("TEST4 message val3=3.3",       (eqt(tbl.getD("VAL3"), 3.3)));
      doAssert("TEST4 message val4=4.4",       (eqt(tbl.getD("VAL4"), 4.4)));
      doAssert("TEST4 message val5=5.5",       (eqt(tbl.getD("VAL5"), 5.5)));
      doAssert("TEST4 message val6=6.6",       (eqt(tbl.getD("VAL6"), 6.6)));
    }
    else if (msg.name.equals("SETL")) {
      Table tbl = Convert.o2t(msg.data);
      doAssert("SETL message fid=" + xmid,     (xmid.equals(msg.getFromID())));
      doAssert("SETL message to="  + nmid,     (nmid.equals(msg.getToID())));
      doAssert("SETL message info=42",         (msg.info   == 42));
      doAssert("SETL message data.getsize=3",  (tbl.size() == 3));
      doAssert("SETL message object=MyObj",    (tbl.getS("OBJECT").equals("MyObj")));
      doAssert("SETL message value=1",         (tbl.getD("VALUE")  == 1));
      doAssert("SETL message value2=2",        (tbl.getD("VALUE2") == 2));

      String passFail = (numFails == 0)? "PASS": "FAIL";
      MR.getRoot().put("XM.STATUS_" + getID(), passFail);

      Table data2 = new Table("{ARGS=3,TYPE=\"DAD\",VAL1=10.0,VAL2=\"Twenty\",VAL3=30.0}");
      Table data3 = new Table("{ARGS=4,TYPE=\"LS[12]S[32]L\",VAL1=1,VAL2=\""+ longstr12 + "\",VAL3=\""+ longstr36 +"\",VAL4=2}");
      Table datas = new Table("{OBJECT=\"NmObj\",VALUE2=30,VALUE=20}");
      Table data4 = new Table("{ARGS=6,TYPE=\"2L2DFF\",VAL1=1,VAL2=2,VAL3=3.3,VAL4=4.4,VAL5=5.5,VAL6=6.6}");
      MQ.put(new Message("TESTN0",  0, null,  XmMsgType.AUTO),         "XM.3"); // AUTO -> Unconfigured Message not sent to macro
      MQ.put(new Message("TESTN1", 10, null,  XmMsgType.UNCONFIGURED), "XM.1"); // AUTO -> Unconfigured Message with no data sent to XM macro
      MQ.put(new Message("TESTN2", 20, data2, XmMsgType.AUTO),         "XM.1"); // AUTO -> Unconfigured message with data

      sendMessage(new Message("TESTN3", 0, data3, XmMsgType.UNCONFIGURED)); // Unconfigured message with string
      sendMessage(new Message("TESTN4", 0, data4, XmMsgType.UNCONFIGURED)); // Unconfigured message type multipliers
      sendMessage(new Message("SETL",  30, datas, XmMsgType.CONFIGURED));   // Configured message with data

      // This next message is a test for Bug 431 (type field length >8 chars)
      Table rerrdata = new Table("{TEXT=\"MYTEXT\",ADDR=\"MYADDR\",FUNC=\"MYFUNC\",DATA=\"MYDATA\"}");
      MQ.put(new Message("RERR", 0, rerrdata, XmMsgType.CONFIGURED), "XM.3"); // Configured message with data

      status = FINISH;
    }
    else {
      doAssert("Got unknown message name="+msg.name, false);
    }

    return status;
  }

  private void doAssert (String msg, boolean status) {
    msg = StringUtil.padRight(msg, 69, '.');

    numTests++;
    if (status) {
      M.info(msg + "PASS");
    } else {
      numFails++;
      M.warning(msg + "FAIL <--");
    }
  }

  private final boolean eqt (double d1, double d2) {
    return Tolerance.equalsWithTolerance(d1, d2);
  }
}
