package nxm.sys.lib;

import java.util.Vector;

import nxm.sys.inc.ListFile;
import nxm.sys.inc.MidasReference;

/** Defines KML functions useful throughout NeXtMidas and NeXtMidas applications.

    @author  J. Bauer
    @since   NeXtMidas 2.7.0
 */
public final class KmlFile extends XmlFile implements KmlFileModSwap, ListFile {
  /** property list */
  public final String propertyList = XmlFile.propertyList+
                     ",XStart,XDelta,XUnits,XFrame,YStart,YDelta,YUnits,YFrame";

  private double xstart   = 0;
  private double xdelta   = 1;
  private double ystart   = 0;
  private double ydelta   = 1;
  private double timecode = 0;

  private int xunits      = 0;
  private int xframe      = 1;
  private int yunits      = 0;
  private int yframe      = 1;

  private String format        = "UNK";
  private Vector<String> lines = null;

  /** KmlFile Default Constructor */
  public KmlFile () { }

  /** KmlFile Constructor
      @param filename name of KmlFile as a String
   */
  public KmlFile (String filename) {
    init(null,filename);
  }

  /** KmlFile Constructor
      @param fn name of KmlFile as a NeXtMidas FileName object
   */
  public KmlFile (FileName fn) {
    init (null,fn);
  }

  /** @param ref      reference
   *  @param filename file name
   *  @deprecated since NeXtMidas 3.5.0 use {@link #KmlFile(MidasReference, Object)}
   */
  @Deprecated
  public KmlFile (Object ref, Object filename) {
    if (ref instanceof MidasReference) {
      init((MidasReference) ref, filename);
    } else {
      init(Convert.ref2Midas(ref), filename);
    }
  }

  /** Constructor
   *  @param ref      Midas Reference
   *  @param filename file name of KML file
   *  @since 3.5.0
   */
  public KmlFile (MidasReference ref, Object filename) {
    init(ref,filename);
  }

  @Override
  public String getMimeType () {
    // TBD: kmz files use "application/vnd.google-earth.kmz"
    return "application/vnd.google-earth.kml+xml";
  }

  @Override
  public void connect(int mode) {}
  @Override
  public String listHeader() {
    String list =
      "KmlFile    :  "+getURL()+"\n"
    + "Version    :  "+"KML2.2 ???\n" /* ??? */
    + "Size       :  "+getSize()+"\n";
/*    + "Format      :  "+getFormat()+"\n"
    + "X units     :  "+DataFile.getUnitsName(getXUnits())+"\n"
    + "X start     :  "+getXStart()+"\n"
    + "X delta     :  "+getXDelta()+"\n"
    + "X frame     :  "+getXFrame()+"\n"
    + "Y units     :  "+DataFile.getUnitsName(getYUnits())+"\n"
    + "Y start     :  "+getYStart()+"\n"
    + "Y delta     :  "+getYDelta()+"\n"
    + "Y frame     :  "+getYFrame()+"\n"
    + "Comment     :  "+getComment()+"\n";
*/
    return list;
  }

  public String getFormat () { return format; }
  public double getStart ()  { return ystart; }
  public double getDelta ()  { return ydelta; }
  public int    getUnits ()  { return yunits; }
  public double getXStart () { return xstart; }
  public double getXDelta () { return xdelta; }
  public int    getXUnits () { return xunits; }
  public int    getXFrame () { return xframe; }
  public double getYStart () { return ystart; }
  public double getYDelta () { return ydelta; }
  public int    getYUnits () { return yunits; }
  public int    getYFrame () { return yframe; }
  public double getTimeAt (double offset) { return timecode; }

  /** Set Kml format
      @param value new Kml format
   */
  public void setFormat (String value) { format = value; }
  /** Set X-axis start value
      @param value new X-axis start value
   */
  public void setXStart (double value) { xstart = value; }
  /** Set X-axis delta
      @param value new X-axis delta
   */
  public void setXDelta (double value) { xdelta = value; }
  /** Set X-axis units
      @param value new X-axis units
   */
  public void setXUnits (int value) { xunits = value; }
  /** Set X-axis frame size
      @param value new X-axis start value
   */
  public void setXFrame (int value) { xframe = value; }
  /** Set Y-axis start value
      @param value new Y-axis start value
   */
  public void setYStart (double value) { ystart = value; }
  /** Set Y-axis delta
      @param value new Y-axis delta
   */
  public void setYDelta (double value) { ydelta = value; }
  /** Set Y-axis units
      @param value new Y-axis units
   */
  public void setYUnits (int value) { yunits = value; }
  /** Set Y-axis frame size
      @param value new Y-axis frame size
   */
  public void setYFrame (int value) { yframe = value; }
  /** Set time code
      @param value new time code
   */
  public void setTimeCode (double value) { timecode = value; }

  public int getMode() { return 1; }

  public int getType() { return 0; }

  public Data getDataBuffer(int size) { return null; } // TODO

  public boolean open () {
    return super.open();
  }

  public int read(Data data, int elements) { return -1; }

  private void readFile() {
    lines = new Vector<>(1024);
    // TODO:
  }

  public final void removeData (double offset) {
    removeData(offset, 1);
  }

  public void removeData (double offset, long count) {
    if (lines == null) { readFile(); }
    Util.removeListElements(lines, (int)offset, (int)count);
  }

  public double getNumberOfRows () {
    return (lines==null)? 0 : lines.size(); // NTN: need this otherwise LIST2 throws a bunch of exceptions (still does not list anything though)
  }

  public void insertData (double offset, Object obj) {
    // TODO:
  }

  public double avail () {
    return 1;
  }

  public int setData (double offset, Table table) {
    setData(offset, "TEXT", table.getS("TEXT", ""));
    return 1;
  }

  public void setData (double element, String fieldName, Object obj) {
    if (lines == null) { readFile(); }
    if (fieldName.equals("TEXT")) {
      lines.set((int)offset, obj.toString());
    }
  }

  public void setRecordDefs (Table defs) {
    if ((defs.size() == 1) && defs.getKeys()[0].equals("TEXT")) {
      // All is good... nothing to do.
    } else {
      throw new MidasException("KmlFile: Can not alter record definitions in a TextFile.");
    }
  }

  public Table getRecordDefs () {
    Table tbl = new Table();
    tbl.setKey("TEXT", getRecordDef(0));
    return tbl;
  }

  public Table getRecordDef (int i) {
    Table tbl = new Table();
    tbl.setKey("NAME", "TEXT");
    return tbl;
  }

  public Table getDataTable (double offset) {
    if (offset < 0) return null;
    if (lines == null) { readFile(); }
    Table tbl = null;

    if ((offset < lines.size()) && (offset >= 0.0)) {
      tbl = new Table();
      tbl.setKey("TEXT", lines.get((int)offset));
    }

    return tbl;
  }

  public boolean getProtected () { return true; }

  public int getRecordDefCount () { return 1; }


  public int readDataTable(Table tbl) {
    // TODO Auto-generated method stub
    return 0;
  }

}
