package nxm.nettest.prim;

import java.rmi.RemoteException;
import java.rmi.registry.Registry;

import nxm.nettest.inc.SampleInterface;
import nxm.nettest.intr.Rmiinterface;
import nxm.sys.inc.InternalUseOnly;
import nxm.sys.lib.Midas;
import nxm.sys.lib.Primitive;
import nxm.sys.lib.StringUtil;
import nxm.sys.lib.Table;

/** Java's RMI sample client to {@link SampleInterface} remote object as a primitive.
    @author Neon Ngo
    @since NeXtMidas 3.1.0
*/
@InternalUseOnly("Since 3.5.2")
public class rmiclient extends Primitive {

  /** RMI registry bind name to find SampleInterface remote object */
  private String bindName     = "SampleRMIServer";
  /** RMI registry hostname */
  private String registryHost = "localhost";
  /** RMI registry port */
  private int    registryPort = Registry.REGISTRY_PORT;
  /** Use RMI Security Manager? */
//  private boolean useSecurityManager = false;

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

  public int open() {
    bindName     = MA.getCS("NAME", bindName);
    registryHost = MA.getCS("HOST", registryHost);
    registryPort = MA.getL("PORT",  registryPort);
//    useSecurityManager = MA.getState("/SECURITY", false);

    runSampleInterfaceClient();
    return FINISH;
  }

  /** launch RMI client for {@link SampleInterface}. */
  void runSampleInterfaceClient () {
    if (verbose) M.info("Starting Java RMI client...");

    // following line removed since SecurityManager is deprecated for removal in JDK17+
    //Rmiinterface.initRMISecurity(useSecurityManager, M);
    Registry registry = Rmiinterface.findRegistry(registryHost, registryPort, M, true);

    try {
      if (verbose) M.info("looking up RMI registry for SampleInterface remote object at name="+bindName);
      SampleInterface remoteSampleObj = (SampleInterface) registry.lookup(bindName);

      M.info("Got SampleInterface (RMI) remote object from registry from name="+bindName);
      testSampleInterface(remoteSampleObj);
    } catch (Throwable e) {
      M.printStackTrace("Java RMI client got exception", e);
    }
  }

  /** utility method to pad specified message to 72 chars before calling M.info(..) */
  void infoMsgPadded (String msg, boolean result) {
    final int  padLen  = 72;
    final char padChar = '.';
    String text = StringUtil.padRight(msg, padLen, padChar) + (result? ".PASS" : ".FAIL <==");
    M.info(text);
  }

  /** Run some tests on the SampleInterface remote object */
  boolean testSampleInterface (SampleInterface sampleIF) {
    boolean testResult = false;
    M.info("Starting SampleInterface tests...");
    try {
      double result = sampleIF.compute(100.0);
      infoMsgPadded("compute(double) " + (verbose? result:""), true);

      String origMsg = "String from RMI Client at " + System.currentTimeMillis();
      String echoMsg =  sampleIF.echo(origMsg);
      boolean isSameMsg = origMsg.equals(echoMsg);
      infoMsgPadded("echo(String) " + (verbose? echoMsg:""), isSameMsg);

      Table  tab = new Table("{a=one,b=2,c=\"Cat\"}") ;
      String tbl2str = sampleIF.toString(tab);
      infoMsgPadded("toString(Table) " + (verbose? tbl2str:""), tbl2str.length()>0);

      Table str2tbl = sampleIF.toTable(new StringBuilder("{FROM=NeXtMidas,VER=3.1}"));
      infoMsgPadded("toTable(StringBuilder) " + (verbose? str2tbl:""), str2tbl.size()>0);

      testResult = true;
    } catch (RemoteException re) {
      M.printStackTrace("Got exception testing SampleInterface remote object", re);
    }

    infoMsgPadded("SampleInterface (RMI client) overall tests results", testResult);
    return testResult;
  }

  /** For running in stand-alone mode outside of NeXtMidas (RMI Client to SampleInterface Remote Object)
      Command-line args: [bindName;DEF=SampleRMIServer] [RmiRegistryHost;DEF=localhost] [RmiRegistryPort;DEF=1099]
      @param args command line arguments
   */
  public static void main (String args[]) {
    rmiclient client = new rmiclient();
    client.setVerbose(true);
    client.M = new Midas(); // need this so that info/debug/warn output have a place to print to

    // parse command-line arguments
    if (args.length>1) { client.bindName     = args[0]; }
    if (args.length>2) { client.registryHost = args[1]; }
    if (args.length>3) { client.registryPort = Integer.parseInt(args[2]); }

    client.runSampleInterfaceClient();
  }
}
