import java.util.*;

public class DataProcessor {
   public static void main(String args[]) {
      if (args.length < 2) {
         System.out.println("USAGE: java DataProcessor (urlOceanside) (urlTorreyPines)");
         System.exit(1);
      }

      String urlOceanside = args[0];
      String urlTorreyPines = args[1];

      // Read sensor data
      SensorReader readerOceanside = new SensorReader(urlOceanside);
      ArrayList datalistOceanside = readerOceanside.getDataList();

      // Find good sailing times (Oceanside)
      ArrayList goodOceanside = findGoodSailingTimes(datalistOceanside);

      // Sort readings by ascending swell wave height (Oceanside)
      ArrayList sortedGoodOceanside = sortInOrder(goodOceanside);

      // Compute average overall wave height (Oceanside)
      double averageOceanside = computeAverage(sortedGoodOceanside);

      // Print output
      System.out.println("Average overall wave height in Oceanside: " + averageOceanside);
      System.out.println("Good sailing times in Oceanside:");
      printDataList(goodOceanside);
      System.out.println("Sorted and filtered good sailing times in Oceanside:");
      printDataList(sortedGoodOceanside);

      // Read sensor data (Torrey Pines)
      SensorReader readerTorreyPines = new SensorReader(urlTorreyPines);
      ArrayList datalistTorreyPines = readerTorreyPines.getDataList();

      // Find good sailing times (Torrey Pines)
      ArrayList goodTorreyPines = findGoodSailingTimes(datalistTorreyPines);

      // Sort readings by ascending swell wave height (Torrey Pines)
      ArrayList sortedGoodTorreyPines = sortInOrder(goodTorreyPines);

      // Compute average overall wave height (TorreyPines)
      double averageTorreyPines = computeAverage(sortedGoodTorreyPines);

       // Print output
      System.out.println("Average overall wave height in Torrey Pines: " + averageTorreyPines);
      System.out.println("Good sailing times in Torrey Pines:");
      printDataList(goodTorreyPines);
      System.out.println("Sorted and filtered good sailing times in Torrey Pines:");
      printDataList(sortedGoodTorreyPines);
   }

   private static double computeAverage(ArrayList list) {
      double sum = 0.0;
      for (int i = 0; i < list.size(); i++) {
         SensorData data = (SensorData)list.get(i);
         sum += data.getOverallWaveHeight();
      }
      return sum / list.size();
   }

   private static void printDataList(ArrayList datalist) {
      for (int i = 0; i < datalist.size(); i++) {
         SensorData data = (SensorData)datalist.get(i);
         System.out.println
            ("On " + 
             data.getMeasurementDate().getTime() + 
             ", the overall wave height was " +
             data.getOverallWaveHeight() + 
             ", the wind wave height was " + 
             data.getWindWaveHeight() +
             ", the swell height was " + 
             data.getSwellWaveHeight() +
             ", and the steepness was " + 
             data.getSteepness()
             );
      }
   }

   private static ArrayList findGoodSailingTimes(ArrayList datalist) {
      ArrayList sailingTimes = new ArrayList();
      for (int i = 0; i < datalist.size(); i++) {
         SensorData data = (SensorData)datalist.get(i);
         if ((data.getWindWaveHeight() >= data.getOverallWaveHeight()) &&
             (data.getSteepness().equals("AVERAGE") || data.getSteepness().equals("SWELL"))) {
            sailingTimes.add(data);
         }
      }
      return sailingTimes;
   }

   private static ArrayList sortInOrder(ArrayList datalist) {
      double maxSwellWaveHeight = 0.5;
      int numDiscarded = 0;
      ArrayList sorted = new ArrayList();
      for (int i = 0; i < datalist.size(); i++) {
         SensorData data = (SensorData)datalist.get(i);
         if (data.getSwellWaveHeight() < maxSwellWaveHeight) {
            // insert in order
            insertInOrder(sorted, data);
         } else {
            numDiscarded++;
         }
      }
      System.out.println("Number of sensor readings discarded due to overly high swell wave height: " + numDiscarded);
      return sorted;
   }

   private static void insertInOrder(ArrayList list, SensorData data) {
      for (int i = 0; i < list.size(); i++) {
         SensorData next = (SensorData)list.get(i);
         if (data.getSwellWaveHeight() <= next.getSwellWaveHeight()) {
            // insert here! (we found a larger element)
            list.add(i, data);
            return;
         }
      }
      // if this is the largest element so far add to end of list
      list.add(data);
   }
}
