// $Id: GribCoordSys.java,v 1.2 2004/12/07 01:29:31 caron Exp $
/*
 * Copyright 1997-2004 Unidata Program Center/University Corporation for
 * Atmospheric Research, P.O. Box 3000, Boulder, CO 80307,
 * support@unidata.ucar.edu.
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at
 * your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
 * General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package ucar.nc2.iosp.grib;

import ucar.ma2.*;
import ucar.nc2.*;
import ucar.nc2.units.SimpleUnit;
import ucar.nc2.dataset.AxisType;
import ucar.grib.Index;
import ucar.grib.TableLookup;

import java.util.*;

/**
 * A Coordinate System for a Grib variable.
 * @author john
 */
public class GribCoordSys {
  private GribHorizCoordSys hcs;
  private Index.GribRecord record;
  private String verticalName;
  private TableLookup lookup;

  private List levels;
  boolean dontUseVertical = false;
  String positive = "up";

  GribCoordSys(GribHorizCoordSys hcs, Index.GribRecord record, String name, TableLookup lookup) {
    this.hcs = hcs;
    this.record = record;
    this.verticalName = name;
    this.lookup = lookup;
    this.levels = new ArrayList();

    dontUseVertical = !lookup.isVerticalCoordinate( record);
    positive = lookup.isPositiveUp(record) ? "up" :"down";
  }

  String getCoordSysName() { return verticalName+"_CoordSys"; }
  String getVerticalName() { return verticalName; }
  int getNLevels() { return levels.size(); }

  void addLevels( List records) {
    for (int i = 0; i < records.size(); i++) {
      Index.GribRecord record = (Index.GribRecord) records.get(i);
      Double d = new Double( record.levelValue1);
      if (!levels.contains(d))
        levels.add(d);
      if (dontUseVertical && levels.size() > 1) {
        System.out.println("unused level coordinate has > 1 levels = "+verticalName+" "+record.levelType1+" "+levels.size());
     }
    }
  }

  void addDimensionsToNetcdfFile( NetcdfFile ncfile, Group g) {
    if (dontUseVertical) return;
    int nlevs = levels.size();
    ncfile.addDimension(g, new Dimension(verticalName, nlevs, true));
  }

  void addToNetcdfFile( NetcdfFile ncfile, Group g) {
    if (dontUseVertical) return;

    String dims = "time";
    if (!dontUseVertical)
      dims = dims + " " + verticalName;
    if (hcs.isLatLon())
      dims = dims + " lat lon";
    else
      dims = dims + " y x";

    Collections.sort( levels);
    int nlevs = levels.size();
    // ncfile.addDimension(g, new Dimension(verticalName, nlevs, true));

    Variable v = new Variable( ncfile, g, null, verticalName);
    v.setDataType( DataType.DOUBLE);

    v.addAttribute( new Attribute("long_name", lookup.getLevelName( record)));
    v.addAttribute( new Attribute("units", lookup.getLevelUnit( record)));

    // positive attribute needed for CF-1 Height and Pressure
    if (positive != null)
      v.addAttribute( new Attribute("positive", positive));

    String units = lookup.getLevelUnit( record);
    if (units != null) {
      AxisType axis;
      if (SimpleUnit.isCompatible("millibar", units))
        axis = AxisType.Pressure;
      else if (SimpleUnit.isCompatible("m", units))
        axis = AxisType.Height;
      else
        axis = AxisType.GeoY;

      v.addAttribute( new Attribute("_CoordinateAxisType", axis.toString()));
      v.addAttribute( new Attribute("_CoordinateAxes", dims));
      if (!hcs.isLatLon())
        v.addAttribute( new Attribute("_CoordinateTransforms", hcs.getGridName()));
    }

    double[] data = new double[nlevs];
    for (int i = 0; i < levels.size(); i++) {
      Double d = (Double) levels.get(i);
      data[i] = d.doubleValue();
    }
    Array dataArray = Array.factory( DataType.DOUBLE.getClassType(), new int [] {nlevs}, data);

    v.setDimensions( verticalName);
    v.setCachedData(dataArray, false);

    ncfile.addVariable( g, v);

    //Variable coordVar = new Variable( ncfile, g, null, getCoordSysName());
    //coordVar.setDataType( DataType.STRING);
    //coordVar.setDimensions( ""); // scalar
    //Array sdataArray = Array.factory( DataType.STRING.getClassType(), new int [] {0}, new String[] {"dummy"});
    //coordVar.setCachedData(sdataArray, true);
    //ncfile.addVariable( g, coordVar);
  }


  int getIndex(Index.GribRecord record) {
    Double d = new Double( record.levelValue1);
    return levels.indexOf( d);
  }
}

/* Change History:
   $Log: GribCoordSys.java,v $
   Revision 1.2  2004/12/07 01:29:31  caron
   redo convention parsing, use _Coordinate encoding.

   Revision 1.1  2004/12/01 05:53:42  caron
   ncml pass 2, new convention parsing

   Revision 1.6  2004/11/11 23:54:13  rkambic
   level stuff

   Revision 1.5  2004/10/29 00:14:11  caron
   no message

   Revision 1.4  2004/10/12 02:57:06  caron
   refactor for grib1/grib2: move common functionality up to ucar.grib
   split GribServiceProvider

   Revision 1.3  2004/10/02 20:54:41  caron
   *** empty log message ***

   Revision 1.2  2004/09/30 20:49:07  caron
   *** empty log message ***

   Revision 1.1  2004/09/30 00:33:41  caron
   *** empty log message ***

*/