// $Id: DqcStationObsDataset.java,v 1.2 2004/11/16 23:35:38 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.thredds;

import ucar.nc2.station.*;

import ucar.nc2.units.SimpleUnit;
import ucar.nc2.units.DateUnit;
import ucar.unidata.geoloc.LatLonRect;

import java.util.*;
import java.io.IOException;

import thredds.catalog.*;
import thredds.catalog.query.*;

/**
 * This implements a StationObsDataset with a DQC
 *
 * @author John Caron
 * @version $Id: DqcStationObsDataset.java,v 1.2 2004/11/16 23:35:38 caron Exp $
 */

public class DqcStationObsDataset implements StationObsDataset {

  static public DqcStationObsDataset factory(QueryCapability dqc) throws IOException {
    // have a look at what selectors there are before proceeding
    SelectStation ss = null;
    SelectRangeDate sd = null;
    SelectService sss = null;
    ArrayList selectors = dqc.getSelectors();
    for (int i = 0; i < selectors.size(); i++) {
      Selector s =  (Selector) selectors.get(i);
      if (s instanceof SelectStation)
        ss = (SelectStation) s;
      if (s instanceof SelectRangeDate)
        sd = (SelectRangeDate) s;
      if (s instanceof SelectService)
        sss = (SelectService) s;
    }
    if (ss == null)
      return null;

    // for the moment, only doing XML
    SelectService.ServiceChoice wantServiceChoice = null;
    List services = sss.getChoices();
    for (int i = 0; i < services.size(); i++) {
      SelectService.ServiceChoice serviceChoice =  (SelectService.ServiceChoice) services.get(i);
      if (serviceChoice.getService().equals("HTTPServer") && serviceChoice.getDataFormat().equals("text/xml"))
        wantServiceChoice = serviceChoice;
    }
    if (wantServiceChoice == null)
      return null;

    return new DqcStationObsDataset( dqc, sss, ss, sd, wantServiceChoice);
  }

  //////////////////////////////////////////////////////////////////////////////////

  private QueryCapability dqc;
  private SelectService selService;
  private SelectStation selStation;
  private SelectRangeDate selDate;
  private SelectService.ServiceChoice service;

  private ArrayList stations = new ArrayList();
  private StationDatasetHelper helper;

  //private DateUnit dateUnit;
  private Date startDate, endDate;

  private boolean debugQuery = false;

  private DqcStationObsDataset(QueryCapability dqc, SelectService selService, SelectStation selStation,
      SelectRangeDate selDate, SelectService.ServiceChoice service) {
    this.dqc = dqc;
    this.selService = selService;
    this.selStation = selStation;
    this.selDate = selDate;
    this.service = service;
    helper = new StationDatasetHelper( this);

    ArrayList stationList = selStation.getStations();
    for (int i = 0; i < stationList.size(); i++) {
      thredds.catalog.query.Station station = (thredds.catalog.query.Station) stationList.get(i);
      stations.add( new DqcStation( station));
    }

    startDate = new Date();
    endDate = new Date();

    //startDate = sd.getStart();
    //endDate = sd.getEnd();

  }

   /** Close all resources associated with this dataset. */
  public void close() throws java.io.IOException {
  }

  public Date getStartDate() {
    return startDate; // dateUnit.getStandardDate( startDate);
  }

  public Date getEndDate() {
    return endDate; // dateUnit.getStandardDate( endDate);
  }

  public LatLonRect getBoundingBox() {
    return helper.getBoundingBox();
  }

  public List getStations() { return stations; }

  public List getStations(LatLonRect boundingBox) throws IOException {
    return helper.getStations(boundingBox);
  }

  public StationObsDataset.Station getStation(String id) {
    return helper.getStation(id);
  }

  public int getStationObsCount(StationObsDataset.Station s) {
    DqcStation si = (DqcStation)s;
    return (si.obs == null)  ? -1 : si.obs.size();
  }

  public List getStationObs(StationObsDataset.Station s, Date start, Date end) throws IOException {
    return helper.getStationObs(s, start, end);
  }

  public List getStationObs(List stations) throws IOException {
    return helper.getStationObs(stations);
  }

  public List getStationObs(List stations, Date start, Date end) throws IOException {
    return helper.getStationObs(stations, start, end);
  }

  public List getStationObs(LatLonRect boundingBox) throws IOException {
    return helper.getStationObs(boundingBox);
  }

  public List getStationObs(LatLonRect boundingBox, Date start, Date end) throws IOException {
    return helper.getStationObs(boundingBox, start, end);
  }

  public void sortByTime(List stationObs) {
    helper.sortByTime(stationObs);
  }

  public List getStationObs( Station s) throws IOException {
    return ((DqcStation)s).getObservations();
  }

  private void makeQuery( ArrayList stations) {
     // construct the query
     StringBuffer queryb = new StringBuffer();
     queryb.append( dqc.getQuery().getUriResolved().toString());
     // selService.appendQuery( queryb, serviceList);
     selStation.appendQuery( queryb, stations);

     String queryString = queryb.toString();
     if (debugQuery) {
       System.out.println("dqc makeQuery= "+queryString);
     }

     // fetch the catalog
     InvCatalogFactory factory = InvCatalogFactory.getDefaultFactory(true); // use default factory
     InvCatalog catalog = factory.readXML( queryString);
     StringBuffer buff = new StringBuffer();
     if (!catalog.check( buff)) {
       // javax.swing.JOptionPane.showMessageDialog(this, "Invalid catalog "+ buff.toString());
       System.out.println("Invalid catalog "+buff.toString());
       return;
     }
     if (debugQuery) {
       System.out.println("dqc/showQueryResult catalog check msgs= "+buff.toString());
       System.out.println("  query result =\n"+thredds.util.IO.readURLcontents(queryString));
     }
   }

  private class DqcStation implements StationObsDataset.Station {
    private String name, desc;
    private double lat, lon, elev;
    private int count = -1;

    private List obs = null;

    private DqcStation( thredds.catalog.query.Station s) {
      this.name = s.getValue();
      this.desc = s.getName();
      //InvDocumentation doc = s.getDescription();
      //this.desc = (doc == null) ? "" : doc.getInlineContent();
      this.lat = s.getLocation().getLatitude();
      this.lon = s.getLocation().getLongitude();
      this.elev = s.getLocation().getElevation();
    }

    public String getName() { return name; }
    public String getDescription() { return desc; }
    public double getLatitude() { return lat; }
    public double getLongitude() { return lon; }
    public double getElevation() { return elev; }

    public int getNumObservations() { return count; }

    public List getObservations() throws IOException {
      if (obs == null)
        obs = findObservations();
      return obs;
    }

    private List findObservations() throws IOException {
      ArrayList obs = new ArrayList();

      return obs;
    }

  }

  public class ObsImpl implements StationObsDataset.StationObs {
    private Station station;
    private double dateValue;
    private int recno;

    private ObsImpl( Station station, double dateValue, int recno) {
      this.station = station;
      this.dateValue = dateValue;
      this.recno = recno;
    }

    public Station getStation() { return station; }
    public Date getTime() {
      return null; // dateUnit.getStandardDate( dateValue);
    }

    public ucar.nc2.StructureData getData() throws IOException {
      return null;
    }
  }

}

/* Change History:
   $Log: DqcStationObsDataset.java,v $
   Revision 1.2  2004/11/16 23:35:38  caron
   no message

   Revision 1.1  2004/09/22 13:46:38  caron
   *** empty log message ***

   Revision 1.4  2004/09/09 22:47:41  caron
   station updates

   Revision 1.3  2004/08/26 17:55:08  caron
   no message

   Revision 1.2  2004/07/12 23:40:18  caron
   2.2 alpha 1.0 checkin

   Revision 1.1  2004/07/06 19:31:59  caron
   pre-alpha checkin

   Revision 1.3  2003/10/28 23:57:21  caron
   minor

   Revision 1.2  2003/10/02 20:33:56  caron
   move SimpleUnit to dataset; add <units> tag; add projections to CF

   Revision 1.1  2003/06/09 15:23:17  caron
   add nc2.ui

   Revision 1.1  2003/04/08 18:19:11  john
   nc2.ui

 */