package nxm.sys.lib;

import nxm.sys.inc.AsciiMap;
import nxm.sys.lib.FileName.FNCase;

/**
  A library of static classes for generate a text file of various formats for a
  named command or library function.

  @author Jay Hallam
*/
public class Generate extends Object implements AsciiMap {
  /** Generate an explain file from comments in source code.
      @param fullSourceName - Source file to parse for explain comments
      @param fullExpName    - Explain file to create
      @param overWrite      - Overwrite existing explain file ONLY if TRUE.
      @return <code> 1</code>&nbsp;=&nbsp;File created,
              <code>-1</code>&nbsp;=&nbsp;Could not create file,
              <code>-2</code>&nbsp;=&nbsp;Could not create file since it
                                          already exists and overwrite is
                                          prohibited.
      @since NextMidas 1.6.0
  */

  /** This constructor was automatically provided by Java,
   *  but it is unneeded as all the methods are static methods.
   *  @deprecated now that Javadocs are required, it is temporarily
   *              being explicitely provided but deprecated
   */
  @Deprecated
  public Generate () {}

  /** Get explain file from commants
   *
   *  @param fullSourceName  Full source name
   *  @param fullExpName     Full explain file name
   *  @param overWrite       overwrite
   *  @return status
   */
  public static int genExplainFromComments (String fullSourceName, String fullExpName, boolean overWrite) {
    int status = -1;
    FileName fnFullSourceName = new FileName(fullSourceName,FNCase.KeepCase);
    TextFile tfi = new TextFile(fnFullSourceName);
    if (tfi.open(TextFile.INPUT|TextFile.NOABORT)) {
      FileName fnFullExpName = new FileName(fullExpName,FNCase.KeepCase);
      TextFile tfo = new TextFile(fnFullExpName);
      if (!overWrite && tfo.find(-1) ) {
        // Explain already exists, NO OVERWRITE privilege!
        status = -2;
      } else {
        if (tfo.open(TextFile.OUTPUT|TextFile.NOABORT)) {
          String line; boolean foundStart = false; boolean foundEnd = false;
          while ((line=tfi.read()) != null) {
            if (line.trim().startsWith ("/**") ) {
              foundStart = true;
              int iEndComment = line.indexOf("*/");
              if (iEndComment >=0) {
                tfo.writeln(line.substring(3,line.indexOf("*/")));
                break;
              }
            } else if (foundStart)  {
              if (line.trim().startsWith ("*/") ) {
                break;
              } else {
                tfo.writeln(line);
              }
            }
          }
          status = 1;
          tfo.close();
        } else {
          // Unable to open explain file for output
        }
      }
      tfi.close();
    } else {
      // Input source file could not be opened.
    }
    return status;
  }

  /** Generate an explain file stub from the source code getting CUEs from the
      arguments, switches and messages in the code.
      @param fullSourceName - Source file to parse
      @param cmdName        - Command Name
      @param fullExpName    - Full explain file name to create
      @param overWrite      - Overwrite existing explain file ONLY if TRUE.
      @param warn           - issue warning if can not find

      @return <code> 1</code>&nbsp;=&nbsp;File created,
              <code>-1</code>&nbsp;=&nbsp;Could not create file,
              <code>-2</code>&nbsp;=&nbsp;Could not create file since it
                                          already exists and overwrite is
                                          prohibited.
      @since NextMidas 1.6.0
  */
  public static int genExplainFromSource (String fullSourceName, String cmdName,
                                          String fullExpName, boolean overWrite, boolean warn) {
    String switchesString = null;
    String tagsString = null;
    String rxMsgString = null;
    String sendMsgString = null;
    int status = -1;
    // Generate the explain file from source code
    FileName fnFullSourceName = new FileName(fullSourceName,FNCase.KeepCase);
    TextFile tfi = new TextFile(fnFullSourceName);
    if (tfi.open(TextFile.INPUT|TextFile.NOABORT)) {
      FileName fnFullExpName = new FileName(fullExpName,FNCase.KeepCase);
      TextFile tfo = new TextFile(fnFullExpName);
      if (!overWrite && tfo.find(-1) ) {
        // Explain already exists, NO OVERWRITE privilege!
        status = -2;
      } else {
        if (tfo.open(TextFile.OUTPUT|TextFile.NOABORT)) {
          String line;
          while ((line=tfi.read()) != null) {
            int iMA = line.indexOf ("MA.");  // Look for parameters
            int iMSG = line.indexOf ("msg.name.equals"); // Look for receive messages
            int iMSGSend = line.indexOf ("MQ.put"); // Look for send messages
            if (iMA >= 0) {
              // Found a MA. reference, should be an argument.
              String mastring = line.substring(iMA);
              String tagName = getTagNameFromString(mastring);
              if (tagName == null) {
                if (warn) Shell.warning("could not find param tag in string '"+mastring+"'");
                tagName = "UNKNOWN";
              }
              if (tagName.startsWith("/")) {
                if (switchesString == null) switchesString = tagName;
                else {
                  if (switchesString.indexOf(tagName) < 0) {
                    switchesString += ","+tagName;
                  }
                }
              } else {
                if (tagsString == null) tagsString = tagName;
                else {
                  if (tagsString.indexOf(tagName) < 0) {
                    tagsString += ","+tagName;
                  }
                }
              }

            }
            if (iMSG >= 0) {
              String msgstr = line.substring(iMSG);
              String tagName = getTagNameFromString (msgstr);
              if (tagName == null) {
                if (warn) Shell.warning("could not find msg tag in string '"+msgstr+"'");
                tagName = "UNKNOWN";
              }
              if (rxMsgString == null) rxMsgString = tagName;
              else {
                if (rxMsgString.indexOf(tagName+",") < 0) {
                  rxMsgString += ","+tagName;
                }
              }

            }
            if (iMSGSend >= 0) {
              String msgstr = line.substring(iMSGSend);
              String tagName = getTagNameFromString (msgstr);
              if (tagName == null) {
                if (warn) Shell.warning("could not find msg tag in string '"+msgstr+"'");
                tagName = "UNKNOWN";
              }
              if (sendMsgString == null) sendMsgString = tagName;
              else {
                if (sendMsgString.indexOf(tagName+",") < 0) {
                  sendMsgString += ","+tagName;
                }
              }

            }
          }  // end of WHILE

          String [] tags = StringUtil.cleanSplit(tagsString, ",");
          String [] rxMsgs = StringUtil.cleanSplit(rxMsgString, ",");
          String [] sendMsgs = StringUtil.cleanSplit(sendMsgString, ",");
          String [] switches = StringUtil.cleanSplit(switchesString, ",");
          makeExpStub (tfo, cmdName, tags, rxMsgs, sendMsgs, switches);
          status = 1;
          tfo.close();
        } else {
          // Unable to open explain file for output
        }
      }
      tfi.close();
    } else {
      // Input source file could not be opened.
    }
    return status;
  }
  /** Make an explain file stub
    @param tfo The output TextFile
    @param cmdName The command name
    @param tags Array of parameter names
    @param rxMsgs Array of received message names
    @param sendMsgs Array of sent message names
    @param switches Array of switch names
  */
  public static void makeExpStub (TextFile tfo, String cmdName, String[] tags,
                                  String[] rxMsgs, String[] sendMsgs, String[] switches) {
    // NAME - Description
    String line = cmdName.toUpperCase()+" - short explanation here";
    tfo.writeln(line);

    // <PARAM 1> - Description
    // ...
    // <PARAM n> - Description
    if (tags != null && tags.length > 0) {
      line = "";
      tfo.writeln(line);
      for (int i = 0; i < tags.length; i++) {
        if (tags[i].length() < 6) line = "<"+tags[i]+">\t\t - Tag description";
        else                      line = "<"+tags[i]+">\t - Tag description";
        tfo.writeln(line);
      }
    }

    // Body - Detailed description here
    line = "";
    tfo.writeln(line);
    line = "Body - Detailed description here";
    tfo.writeln(line);

    // MSGNAMEs - Description
    if (rxMsgs != null && rxMsgs.length > 0) {
      line = "";
      tfo.writeln(line);
      line = "Messages:";
      tfo.writeln(line);
      line = "  Receive:";
      tfo.writeln(line);
      for (int i = 0; i < rxMsgs.length; i++) {
        if (rxMsgs[i].length() < 6) line = "    "+rxMsgs[i]+"  \t - Msg description";
        else                       line = "    "+rxMsgs[i]+"\t - Msg description";
        tfo.writeln(line);
      }
    }
    if (sendMsgs != null && sendMsgs.length > 0) {
      line = "  Send:";
      tfo.writeln(line);
      for (int i = 0; i < sendMsgs.length; i++) {
        if (sendMsgs[i].length() < 6) line = "    "+sendMsgs[i]+"  \t - Msg description";
        else                       line = "    "+sendMsgs[i]+"\t - Msg description";
        tfo.writeln(line);
      }
    }

    // Examples:
    line = "";
    tfo.writeln(line);
    line = "Examples:";
    tfo.writeln(line);

    // Switches:
    //   SWITCHNAME=
    if (switches != null && switches.length > 0) {
      line = "";
      tfo.writeln(line);
      line = "Switches:";
      tfo.writeln(line);
      for (int i = 0; i < switches.length; i++) {
        line = "  "+switches[i]+" - Switch description";
        tfo.writeln(line);
      }
    }
  }

  /** Get the tag name from a string.  For example MA.get...("TAG").
      @param mastring The string from which to find the tag name
      @return tag name
  */
  public static String getTagNameFromString (String mastring) {
    String tagName = null;
    // Find the left and right parens
    int iLParen = mastring.indexOf( ""+LPAREN );
    int iRParen = mastring.indexOf( ""+RPAREN );
    if (iLParen >= 0 && iRParen > iLParen) {
      // The argument tag name is between the parens
      String betweenParens = mastring.substring(iLParen+1, iRParen);
      int iQuote1 = betweenParens.indexOf(""+QUOTE);
      if (iQuote1 >= 0) {
        int iQuote2 = betweenParens.substring(iQuote1+1).indexOf(QUOTE);
        if (iQuote2 >= 0) {
          tagName = betweenParens.substring(iQuote1+1,iQuote2+1);
        }
      }
    } else {
      // No LEFT and/or RIGHT paren
    }
    return tagName;
  }


}
