package nxm.sys.lib;

/**
  Resource for interacting with a local File using native code.

  <table border="1">
    <caption style="visibility:hidden">""</caption>
    <tr>
      <th colspan="2">Special File Qualifiers</th>
    </tr>
    <tr>
      <th>Qualifier</th>
      <th>Description</th>
    </tr>
    <tr>
      <td>DELETEONEXIT</td>
      <td>Requests that the file be deleted when the JVM exits normally after the file is opened
          successfully. See {@link java.io.File#deleteOnExit()} for details. Once deletion has been
          requested, it is not possible to cancel the request.
          Since NeXtMidas 3.1.1.</td>
    </tr>
  </table>
  @author Jeff Schoen
*/
public class NFileResource extends FileResource {

  private int fd;

  /** NFileResource Default Constructor */
  public NFileResource() { super(); }

  /** open the resource */
  @Override
  public boolean open () {
    isOpen = false;
    fd = Native.fopen (file.toString(),dir);
    isOpen = (fd > 0);

    if (isOpen && getStateQualifier("DELETEONEXIT")) { // since 3.1.1 for BUG 2538
      file.deleteOnExit();
    }

    return isOpen;
  }

  /** close the resource */
  @Override
  public boolean close() {
    if (!isOpen) return false;
    Native.fclose(fd);
    isOpen = false;
    return true;
  }

  /** seek to the specified offset in file */
  @Override
  public boolean seek (long offset) {
    if (offset==this.offset) return true;
    if (Native.fseek(fd,offset) != offset) return false;
    this.offset = offset;
    return true;
  }

  /** read data from resource into specified byte array buffer. */
  @Override
  public int read (byte[] buf, int boff, int bytes) {
    int status=0, off=boff;
    while (bytes>0) {
      status = Native.freadb(fd,buf,off,bytes);
      if (status>0) { bytes-=status; off+=status; }
      else break;
    }
    bytes = off-boff;                               // bytes read
    // if (status<1) M.type("DEBUG: NFileResource.read(byte[]..) status="+status+" bytes read="+bytes);
    // ORIG 2.7.0 if (status<0 && bytes==0)  return status;
    if (status==0 && bytes==0) return -1;           // EOF
    if (status<0  && bytes==0) return CoreIO.ERROR; // error during read
    offset += bytes;
    return bytes;
  }

  /** write data to resource */
  @Override
  public int write (byte[] buf, int boff, int bytes) {
    int status, off=boff;
    status = Native.fwriteb(fd,buf,off,bytes);
    offset += bytes;
    return bytes;
  }

  /** read data from resource into native pointer to buffer. */
  @Override
  public int read (long lbuf, int boff, int bytes) {
    int status=0, off=boff;
    while (bytes>0) {
      status = Native.fread(fd,lbuf,off,bytes);
      if (status>0) { bytes-=status; off+=status; }
      else break;
    }
    bytes = off-boff;                               // bytes read
    // if (status<1) M.type("DEBUG: NFileResource.read(long..) status="+status+" bytes read="+bytes);
    // ORIG 2.7.0 if (status<0 && bytes==0) return status;
    if (status==0 && bytes==0) return -1;           // EOF
    if (status<0  && bytes==0) return CoreIO.ERROR; // error during read
    offset += bytes;
    return bytes;
  }

  /** write data to resource */
  @Override
  public int write (long lbuf, int boff, int bytes) {
    int status, off=boff;
    status = Native.fwrite(fd,lbuf,off,bytes);
    offset += bytes;
    return bytes;
  }

  /** Return a printable string containing information about this object. */
  public String toString () { return "NativeFileResource : " + getURL(); }

}
