/*
      Final Output format, save information in DatasetEntry de
       <dataset name="Level2_KFTG_20100121_0000.ar2v" ID="735519521"
          urlPath="KFTG/20100121/Level2_KFTG_20100121_0000.ar2v">
          <date type="start of ob">2010-01-21T00:00:00</date>
        </dataset>
  */
  private Boolean processQuery(
      String dataset, QueryParams qp, String var, List<DatasetEntry> entries)
      throws RadarServerException {

    Boolean getAllTimes = true;
    String yyyymmddStart = null;
    String yyyymmddEnd = null;
    String dateStart = null;
    String dateEnd = null;
    try {
      if (!qp.time_start.equals(epicDateType)) {
        getAllTimes = false;
        yyyymmddStart = qp.time_start.toDateString();
        yyyymmddStart = yyyymmddStart.replace("-", "");
        yyyymmddEnd = qp.time_end.toDateString();
        yyyymmddEnd = yyyymmddEnd.replace("-", "");
        dateStart = yyyymmddStart + "_" + RadarServerUtil.hhmm(qp.time_start.toDateTimeString());
        dateEnd = yyyymmddEnd + "_" + RadarServerUtil.hhmm(qp.time_end.toDateTimeString());
      }

      RadarDatasetCollection rdc = DatasetRepository.getRadarDatasetCollection(dataset, var);
      if (rdc == null) {
        qp.errs.append("Invalid dataset =").append(dataset);
        qp.errs.append(" or var =").append(var);
        return false;
      }
      StringBuffer time = new StringBuffer();
      StringBuffer product = new StringBuffer();
      StringBuffer url = new StringBuffer();
      boolean isLevel2 = dataset.contains("level2");
      String type = (isLevel2 ? "Level2" : "Level3");
      String suffix = (isLevel2 ? ".ar2v" : ".nids");
      Calendar cal = Calendar.getInstance(java.util.TimeZone.getTimeZone("GMT"));
      Date now = cal.getTime();
      String currentDay = dateFormat.format(now);

      for (String stn : qp.stns) {
        RadarStationCollection rsc = rdc.queryStation(stn, currentDay);
        if (rsc == null) continue;
        for (String day : rsc.getDays()) {
          // check for valid day
          if (!getAllTimes && !RadarServerUtil.isValidDay(day, yyyymmddStart, yyyymmddEnd))
            continue;
          ArrayList<String> tal;
          if (rdc.isCaseStudy()) { //
            tal = rsc.getHourMinute("all");
            for (String prod : tal) {
              // check times
              if (!getAllTimes && !RadarServerUtil.isValidDate(prod, dateStart, dateEnd)) continue;
              // save this entry
              DatasetEntry de = new DatasetEntry();
              int idx = prod.indexOf('/');
              if (idx > 0) {
                de.setName(prod.substring(idx + 1));
              } else {
                de.setName(prod);
              }
              de.setID(Integer.toString(prod.hashCode()));
              url.setLength(0);
              url.append(stn).append("/");
              if (var != null) {
                url.append(var).append("/");
              }
              url.append(prod);
              de.setUrlPath(url.toString());
              de.setDate(RadarServerUtil.getObTimeISO(prod));
              entries.add(de);
            }
            continue;
          } else {
            tal = rsc.getHourMinute(day);
          }
          if (tal == null) continue;
          for (String hm : tal) {
            time.setLength(0);
            time.append(day).append("_").append(hm);
            if (!getAllTimes && !RadarServerUtil.isValidDate(time.toString(), dateStart, dateEnd))
              continue;

            // save this entry
            DatasetEntry de = new DatasetEntry();

            product.setLength(0);
            product.append(type).append("_").append(rsc.getStnName()).append("_");
            if (!isLevel2) product.append(var).append("_");
            product.append(day).append("_").append(hm).append(suffix);

            de.setName(product.toString());
            de.setID(Integer.toString(product.toString().hashCode()));
            url.setLength(0);
            if (!isLevel2) {
              url.append(var).append("/");
            }
            url.append(rsc.getStnName())
                .append("/")
                .append(day)
                .append("/")
                .append(product.toString());
            de.setUrlPath(url.toString());
            de.setDate(RadarServerUtil.getObTimeISO(product.toString()));
            entries.add(de);
            if (qp.hasTimePoint) break;
          }
          if (qp.hasTimePoint) break;
        }
      }
      return true;
    } catch (Throwable e) {
      log.error("Invalid dataset =" + dataset + " or var =" + var, e);
      log.info(
          "handleRequestInternal(): "
              + UsageLog.closingMessageForRequestContext(HttpServletResponse.SC_BAD_REQUEST, -1));
      throw new RadarServerException("Invalid dataset =" + dataset + " or var =" + var);
    }
  }
  // get/check/process query
  public void radarQuery(HttpServletRequest req, HttpServletResponse res, Map<String, Object> model)
      throws ServletException, IOException, RadarServerException {

    //      long  startms = System.currentTimeMillis();
    //      long  endms;
    DatasetRepository.RadarType radarType = DatasetRepository.RadarType.nexrad;
    // need to extract data according to the (dataset) given
    String pathInfo = req.getPathInfo();
    if (pathInfo == null) pathInfo = "";
    if (pathInfo.startsWith("/")) pathInfo = pathInfo.substring(1);
    try {
      String rt = pathInfo.substring(0, pathInfo.indexOf('/', 1));
      radarType = DatasetRepository.RadarType.valueOf(rt);
    } catch (Exception e) {
      log.info("Invalid dataset url reference " + pathInfo);
      throw new RadarServerException("Invalid dataset url reference " + pathInfo);
    }
    Boolean level2 = pathInfo.contains("level2");

    // parse the input
    QueryParams qp = new QueryParams();
    if (!qp.parseQuery(
        req,
        res,
        new String[] {QueryParams.XML, QueryParams.HTML, QueryParams.RAW, QueryParams.NETCDF})) {
      // log.error( "parseQuery Failed "+ qp.errs.toString() + req.getQueryString() );
      // throw new RadarServerException( qp.errs.toString() );//+ req.getQueryString() );
      return; // TODO: uncomment above 2 lines when QueryParams exception is fixed
    }
    //      endms = System.currentTimeMillis();
    //      System.out.println( "after QueryParams "+ (endms - startms));
    //      startms = System.currentTimeMillis();
    // check Query Params
    if (!checkQueryParms(radarType, qp, level2)) {
      log.error("checkQueryParms Failed " + qp.errs.toString() + req.getQueryString());
      throw new RadarServerException(qp.errs.toString()); // + req.getQueryString() );
    }
    //      endms = System.currentTimeMillis();
    //      System.out.println( "after checkQueryParms "+ (endms - startms));
    //      startms = System.currentTimeMillis();

    // check type of output wanted XML html
    qp.acceptType = qp.acceptType.replaceFirst(".*/", "");

    // creates first part of catalog
    if (!createHeader(radarType, qp, pathInfo, model)) {
      log.error("Write Header Failed " + qp.errs.toString() + req.getQueryString());
      throw new RadarServerException(qp.errs.toString()); // req.getQueryString() );
    }
    //      endms = System.currentTimeMillis();
    //      System.out.println( "after writeHeader "+ (endms - startms));
    //      startms = System.currentTimeMillis();
    // gets products according to stations, time, and variables
    boolean dataFound = false;
    List<DatasetEntry> entries = new ArrayList<DatasetEntry>();
    if (qp.vars == null) {
      dataFound = processQuery(pathInfo, qp, null, entries);
      if (releaseDataset) DatasetRepository.removeRadarDatasetCollection(pathInfo, null);
    } else {
      int count = 0;
      for (String var : qp.vars) {
        dataFound = processQuery(pathInfo, qp, var, entries);
        if (dataFound) count++;
        if (releaseDataset) DatasetRepository.removeRadarDatasetCollection(pathInfo, var);
      }
      if (count > 0) dataFound = true;
    }
    // save entries
    model.put("datasets", entries);
    if (dataFound) {
      model.put("documentation", Integer.toString(entries.size()) + " datasets found for query");
    } else if (qp.errs.length() > 0) {
      model.put("documentation", qp.errs.toString());
    } else {
      model.put("documentation", "No data available for station(s) and time range");
    }

    //      endms = System.currentTimeMillis();
    //      System.out.println( "after radarQuery "+ (endms - startms));
    //      startms = System.currentTimeMillis();

  } // end radarNexradQuery