package nxm.sys.libg;

import java.awt.Color;

import nxm.sys.inc.PlotFile;
import nxm.sys.lib.Args;
import nxm.sys.lib.DataFile;
import nxm.sys.lib.Table;
import nxm.sys.prim.plot;

/**
  A class to hold a layer of line segments or filled polygons.

  @author Jeff Schoen
*/
public class LayerPoly extends Layer {
  /** float buffer containing metadata and data
   *  <pre>
   *  for each set of points:
   *  [npts][ncol][xmin][ymin][xmax][ymax][x][y][x][y].....
   *  </pre>
   */
  /** buffer holding coordinates */ public  float[] fbuf;
  /** dimensions */                 public  int     dim  = 2;
  private float[] ftmp = new float[6];
  private Table   ctab;
  private boolean showWarning = true; // flag to show invalid color # warning in file the first time
  private static boolean autoAdjustLineColor = false; // NXM-3574 3.9.3 - allows line color to follow colormap, so LEGEND renders correctly

  /** Default constructor. */
  public LayerPoly () {
    super("POLY");
  }

  /** Constructor that takes in a colormap option. This constructor is used by
      DataFile.getLayer with a value of {@link MColor#MAPLINE}. This
      constructor is public for the benefit of subclasses of {@link LayerPoly}.
      @param cmap The color map to use.
   */
  public LayerPoly (int cmap) {
    this();
    setColorMap(cmap);
    if (cmap==MColor.MAPLINE) ctab = MColor.getMapColorTable();
  }

  /** Constructor that takes in a color table
   *  @param ctab color table
   */
  public LayerPoly (Table ctab) {
    this();
    setColorTable(ctab);
  }

  @Override
  protected void init (plot p, String layerName, int layerIndex, Layer oldLayer) { // since 3.3.2
    super.init(p, layerName, layerIndex, oldLayer);
    if (!(Theme.getOption(Theme.SWING) && Theme.getOption(Theme.SWINGDB))) {
      // Gives user option of turning off backing store and not having it turned back on by layerpoly automatically since 3.9.3
      MP.setOptions("+BS");
    }
  }

  @Override
  public int getDefaultView () { // since 3.3.2
    if (pf == null) return super.getDefaultView();
    switch (pf.getType()) {
      case 1998: return MPlot.V_XYZ;
      case 1999: return MPlot.V_LATLON;
      default:   return super.getDefaultView();
    }
  }

  @Override
  public boolean setFile (PlotFile pf, Table tab, Args MA) {
    super.setFile(pf,tab,MA);
    dim = pf.getMode();
    showWarning = true;
    return true;
  }

  @Override
  public void process () {
    ndata = 0; if (data==null) return;
    ndata = data.size * data.ape;
    fbuf = new float[ndata*dim];
    data.toArray(fbuf);
  }

  @Override
  public void findRange () {
    int j,k,npts,ncol; float xy;
    x1=+180; x2=-180; y1=+90; y2=-90; z1=0; z2=0;
    for (j=0; j<ndata*dim; j=k) {
      npts = (int)fbuf[j];
      ncol = (int)fbuf[j+1];
      k = j + (3+npts)*dim;
      if (ncol== -998) continue;
      j += dim;
      xy = fbuf[j++];  if (xy<x1) x1=xy;
      xy = fbuf[j++];  if (xy<y1) y1=xy;
      if (dim==3) { xy = fbuf[j++];  if (xy<z1) z1=xy; }
      xy = fbuf[j++];  if (xy>x2) x2=xy;
      xy = fbuf[j++];  if (xy>y2) y2=xy;
      if (dim==3) { xy = fbuf[j++];  if (xy>z2) z2=xy; }
    }
    a1=y1; a2=y2;
  }

  @Override
  public void draw (int flag) {
    super.draw(flag);
    int i,j,k,npts,ncol;
    if (ndata<=0) return;

    Line lin = line.copy();

    for (j=0; j<ndata*dim && !MP.cancel; j=k) {
      npts = (int)fbuf[j];
      ncol = (int)fbuf[j+1];
      if (showWarning && (ncol!=fbuf[j+1])) {
        // non-integer color number (potentially bad data) - print warning 1st time
        showWarning = false;
        warning("LayerPoly: expecting integer color number, but got " + fbuf[j+1]);
      }
      k = j + (3+npts)*dim;
      j += dim;
      if (MP.view==MPlot.V_LATLONCONTINUOUS) {
        // Continuous Lat Lon needs a more sophisticated range check - since 3.9.0 for NXM-3284
        if (fbuf[j]>=MP.rx2)   continue;
        if (fbuf[j+1]>=MP.ry2) continue;
        j += dim;
        if ((fbuf[j]<=MP.rx1) && !((fbuf[j-dim] + MPlot.LONGITUDE_RANGE) < MP.rx2)) continue;  // xmax less than xmin AND xmin not within extended continuous range
        if (fbuf[j+1]<=MP.ry1) {continue;}
        j += dim;
      }
      else if (MP.is2D) {
        if (fbuf[j]>=MP.rx2) continue;
        if (fbuf[j+1]>=MP.ry2) continue;
        j += dim;
        if (fbuf[j]<=MP.rx1) continue;
        if (fbuf[j+1]<=MP.ry1) continue;
        j += dim;
      }
      else if (MP.view==MPlot.V_GEODETIC || MP.view==MPlot.V_XYZ) {
        i = MP.viewer.rwc2pix (fbuf,j,dim,2,MP.tpix);
        if (i!=0) { // need to draw, else try alternate corners
          // pass
        }
        else if (dim==2) {
          ftmp[0]=fbuf[j]; ftmp[1]=fbuf[j+3];
          ftmp[2]=fbuf[j+2]; ftmp[3]=fbuf[j+1];
          i = MP.viewer.rwc2pix (ftmp,0,dim,2,MP.tpix);
        }
        else if (dim==3) {
          ftmp[0]=fbuf[j]; ftmp[1]=fbuf[j+3]; ftmp[2]=fbuf[j+5];
          ftmp[3]=fbuf[j+3]; ftmp[4]=fbuf[j+1]; ftmp[5]=fbuf[j+2];
          i = MP.viewer.rwc2pix (ftmp,0,dim,2,MP.tpix);
        }
        j += 2*dim;
        if (i==0) continue;
      }
      else {
        j += 2*dim;
      }
      if (ncol== -998) continue;
      if (ncol== -999) { k=j; continue; }  // <-- TODO: New k val is never used...?
      if (ncol<1) {
        // There are "special" colors handled by X-Midas' XGEOPLOT which we need to handle here.
        lin.setColor(MColor.getSpecialXMidasColor(ncol));
      }
      else {
        int colorIndex = ((ncol-1)%(colors.length-1)) +1; // for 1..(color.length-1)
        lin.setColor(colors[colorIndex]);
      }
      MP.drawLine (fbuf,j,dim,npts,lin);
    } // end for loop
  }

  /** return a table with the current color values
   *  @return a table with the current color values */
  public Table getColorTable() {
    return ctab;
  }

  /** set current color values to this table
   *  @param ctab the current color values to this table */
  public void setColorTable (Table ctab) {
    setColorMap(MColor.getColorMap(ctab));
    this.ctab = ctab;
  }

  // OVERRIDE of Layer methods to allow Line color to auto adjust with ColorMap change
  // this DOES NOT handle the case where the MMB line menu is used to update line color
  // Added in 3.9.3 for NXM-3574

  @Override
  public void setColor (String value) {
    super.setColor(value);
    if (autoAdjustLineColor && (colors != null) && (colors.length > 1)) colors[1] = line.getColor();

  }

  @Override
  public void setColor (int value) {
    super.setColor(value);
    if (autoAdjustLineColor && (colors != null) && (colors.length > 1)) colors[1] = line.getColor();
  }

  @Override
  public void setColor (Color value) {
    super.setColor(value);
    if (autoAdjustLineColor && (colors != null) && (colors.length > 1)) colors[1] = line.getColor();
  }

  /** Enable / Disable the auto adjustment of line color based on the colormap
   *  @param matchColormap true if line color should be last color in colormap
   *  @since NeXtMidas 3.9.3
   */
  public static void setAutoAdjustLineColor (boolean matchColormap) {
    autoAdjustLineColor = matchColormap;
  }

  /** Get value of  auto adjustment of line color based on the colormap
   *  @return true if autoadjustment is on
   *  @since NeXtMidas 3.9.4
   */
  public static boolean getAutoAdjustLineColor () {
    return autoAdjustLineColor;
  }

  @Override
  public void setColors (String value) {
    setColorMap(value);
  }

  @Override
  public void setColorMap (String value) {
    super.setColorMap(value);
    if (autoAdjustLineColor && (colors != null) && (colors.length > 1)) line.setColor(colors[1]);
  }

  @Override
  public void setColorMap (int value) { setColorMap(value,-1); }

  @Override
  public void setColorMap (int value, int ncolors) {
    super.setColorMap(value, ncolors);
    if (autoAdjustLineColor && (colors != null) && (colors.length > 1)) line.setColor(colors[1]);
  }

}
