package nxm.sys.intr;

import nxm.sys.inc.ListFile;
import nxm.sys.lib.BaseFile;
import nxm.sys.lib.Convert;
import nxm.sys.lib.DataFile;
import nxm.sys.lib.Intrinsic;
import nxm.sys.lib.KeyObject;
import nxm.sys.lib.Parser;
import nxm.sys.lib.Shell;
import nxm.sys.lib.StringUtil;

/**
  Displays the contents of a Midas file header.

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

  static final String positionalKeys = "FILE,SZ,XS,XD,XU,FS,YS,YD,YU,TYPE,FORMAT";

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

  public int open () {
    // Open the file
    BaseFile file = MA.getFile ("FILE");
    file.open();

    // Extract named fields into results parameters
    for (int n=2; n<=MA.numberOf(); n++) {
      String key = MA.getKey(n);
      String label = MA.getU(key);
      if (label.length()==0) continue;

      // if no key given, treat as X-Midas positional syntax
      if (key.equals("P"+n)) key = Parser.get(positionalKeys,n);

      Object value = null;
      if (file instanceof DataFile) {
        // Special cases for X-Midas backwards compatibility
        if      (key.equalsIgnoreCase("SZ")) key = "SIZE";
        else if (key.equalsIgnoreCase("DS")) key = "DATASTART";
        else if (key.equalsIgnoreCase("XU")) key = "XUNITS";
        else if (key.equalsIgnoreCase("YU")) key = "YUNITS";

        // Get record definitions for type 3000 or 5000 files
        if (key.startsWith("SR(") || key.startsWith("C(")) {
          value = getSubRecord((ListFile)file, key);
        }
      }
      if (value==null) value = KeyObject.getKey(file,key);

      if (value!=null) MR.put (label,value);
      else M.println ("Bad parameter syntax: "+key+"="+label);  // since 3.7.1 using M.println instead of M.terminal.writeln to allow logging - NXM-1813
    }

    // display the Header status to the user terminal
    if (MA.numberOf() == 1) M.print( file.listHeader() );

    // display the keyword status to the user terminal
    if (MA.getState("/K") || MA.getState("/KEY")) M.print( file.listKeywords() );

    // display the timeline status to the user terminal - added /TIME in 2.7.3 for BUG 2021
    if (MA.getState("/T") || MA.getState("/TIME") && file instanceof DataFile) {
      DataFile df = (DataFile)file;
      if (df.getTimeLineHandler() == null) {
        M.warning("There are no TIMELINE keywords in "+df.getURL());
      } else {
        int decimalPlaces = MA.getL("/PRECISION", MA.getL("/PREC",3)); // since 3.3.0 for BUG 2675
        M.print(df.getTimeLineHandler().list(decimalPlaces));
      }
    }
    // display the data status to the user terminal
    if (MA.find("/D") || MA.find("/DATA")) { // added /DATA in 2.7.3 for BUG 2021
      String dataElsToList = MA.getS("/D", MA.getS("/DATA"));
      // since 3.5.4, added /CMDRUNMODE=RunToCompletion for BUG 2879
      Shell.runCommand(M, "DATALIST/CMDRUNMODE=RunToCompletion," + file.getFileName() + ",0," + dataElsToList);
    }

    file.close ();

    return FINISH;
  }

  /** Helper wrapper to support the old X-Midas syntax of C(n) or SR(n) for record-based
      3000 or 5000 files.  Number parsed from the key is a one-based number to best match
      what is already implemented in HEADERMOD.
   */
  private nxm.sys.lib.Table getSubRecord(ListFile listFile, String key) {
    // The KEY can be:
    //  1) a number like SR(1) or
    //  2) a result like like SR(myres) or
    //  3) a record name like SR(NAME) or SR("NAME")
    nxm.sys.lib.Table retVal = null;
    int iLParen = key.indexOf("(");
    int iRParen = key.indexOf(")");
    String numOrString = key.substring(iLParen+1,iRParen);
    double dIndex = -1;

    // Get the string as a number, pure string or result containing either a number or a string
    Object recObject = Convert.o2o(numOrString, '_', this);
    if (recObject != null) {
      if (StringUtil.isNumber(""+recObject)) dIndex = Convert.o2d(recObject);
      else numOrString = ""+recObject;
    }

    // Now we know it is a number or a String. Form table like...
    //    {NAME=POS,FORMAT=VD,TYPE=GEODETIC,UNITS=DISTANCE}
    if (dIndex != -1) {  // ... a record number
      retVal = listFile.getRecordDef((int)(dIndex-1)); // Need to use an offset 0..n-1
    } else {
      try {              // ... a record name
        nxm.sys.lib.Table allRecDefs = listFile.getRecordDefs();
        if (allRecDefs.containsKey(numOrString)) { retVal = allRecDefs.getTable(numOrString); }
        else                                     { M.warning("STATUS: Unable to find key '"+numOrString+"' in file"); }
      } catch (Exception e) {
        M.warning("Unable to find subrecord in string "+key);
      }
    }

    return retVal;
  }

}
