package nxm.ucl.prim;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.LinkedList;

import nxm.sys.lib.Convert;
import nxm.sys.lib.Message;
import nxm.sys.lib.Primitive;
import nxm.sys.lib.Table;

/**
  Displays the last N lines of a file.

  @author Lisa M. Tursky
*/
public class tail extends Primitive {

  private File file;
  private static final int T_TERM=1, T_TABLE=2;
  private static final int INIT=0, RUN=1, DONE=2;
  private int numLines,outtype=T_TERM,rowCounter=1,state=INIT;
  private long filePointer,length;
  private String fileName,funct,outTableName;
  private double size=0, newSize=0;

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

  public int open () {
    //open input file
    fileName = MA.getS("FILE");
    file = new File(fileName);
    if (!file.exists()) return FINISH;

    //get optional parameters
    outtype = MA.getSelectionIndex("/OUTTYPE", "T_TERM,T_TABLE",T_TERM);
    outTableName = MA.getS("TABLE");
    funct = MA.getS("FUNC", "ONESHOT");
    numLines = MA.getL("LINES", 10);
    LinkedList<String> fileLines = new LinkedList<>();
    filePointer = file.length();

    //read all data the first time, saving only the last numLines
    try {
      RandomAccessFile raf = new RandomAccessFile(file, "r");
      String aLine = null;
      while ((aLine=raf.readLine())!=null) {
        fileLines.addLast(aLine);
        if (fileLines.size() > numLines) {
          fileLines.removeFirst();
        }
      }
      raf.close();
    }
    catch (IOException ioe) {
      M.warning("Error accessing file.");
      return FINISH;
    }
    //write out the last numLines to the Midas Terminal
    for (String value : fileLines) {
      if (outtype == T_TERM) {
        M.println(value);  // since 3.7.1 use M.println instead of M.terminal.writeln to allow logging of interactive command NXM-2813
      } else {
        Table outTable = Convert.o2t(MR.get(outTableName));
        outTable.put("ROW_"+rowCounter,value);
        rowCounter++;
      }
    }
    return NORMAL;
  }

  public int process () {

  //if oneshot return the requested tail and finish
    if (funct.equals("ONESHOT")) {
      return FINISH;
    }
    //else if in SERVER mode, keep processing
    else {
      try {
        Thread.sleep(3000);
      } catch (InterruptedException ie) { } // ignore
      try {

      //If file length has changed, stuff has been added to file.
      //Get all new lines and print to terminal
        length = file.length();
        if (length > filePointer) {
          RandomAccessFile raf = new RandomAccessFile(file,"r");
          raf.seek(filePointer);
          String aLine = null;
          while ((aLine=raf.readLine())!=null) {
            if (outtype == T_TERM) {
               M.println(aLine);
            } else {
              Table outTable = Convert.o2t(MR.get(outTableName));
              outTable.put("ROW_" + rowCounter, aLine);
              rowCounter++;
            }
          }
          filePointer = raf.getFilePointer();
          raf.close();
        }//end if
      }
      catch (IOException ioe) {
        state = DONE;
      }
      return(NORMAL);
    }//end else
  }

  public int processMessage (Message msg) {
    M.info("TAIL: got message " + msg.name + " data " + msg.data);
    if (msg.name.equals("CLOSE")) {
      close();
    }
    return NORMAL;
  }

  public int close () {
    state = DONE;
    return NORMAL;
  }

}
