package net.maxbraun.mirror;

import android.content.Context;
import android.location.Location;
import android.util.Log;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import net.maxbraun.mirror.Air.AirData;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * A helper class to regularly retrieve air quality information.
 */
public class Air extends DataUpdater<AirData> {
  private static final String TAG = Air.class.getSimpleName();

  /**
   * The time in milliseconds between API calls to update the air quality.
   */
  private static final long UPDATE_INTERVAL_MILLIS = TimeUnit.MINUTES.toMillis(15);

  /**
   * The base URL for all AirNow API requests.
   */
  private static final String AIR_NOW_BASE_URL = "https://www.airnowapi.org";

  /**
   * The context used to load string resources.
   */
  private final Context context;

  /**
   * A {@link Map} from the air quality index category the corresponding drawable resource ID.
   */
  private final Map<Integer, Integer> iconResources = new HashMap<Integer, Integer>() {{
    put(1, R.drawable.aqi_good);
    put(2, R.drawable.aqi_moderate);
    put(3, R.drawable.aqi_usg);
    put(4, R.drawable.aqi_unhealthy);
    put(5, R.drawable.aqi_very_unhealthy);
    put(6, R.drawable.aqi_hazardous);
  }};

  /**
   * The data structure containing the air quality information we are interested in.
   */
  public class AirData {

    /**
     * The air quality index number.
     */
    public final int aqi;

    /**
     * The air quality index category name.
     */
    public final String category;

    /**
     * The air quality index category icon.
     */
    public final int icon;

    public AirData(int aqi, String category, int icon) {
      this.aqi = aqi;
      this.category = category;
      this.icon = icon;
    }
  }

  public Air(Context context, UpdateListener<AirData> updateListener) {
    super(updateListener, UPDATE_INTERVAL_MILLIS);
    this.context = context;
  }

  @Override
  protected AirData getData() {
    Location location = GeoLocation.getLocation();
    Log.d(TAG, "Using location for air quality: " + location);

    // Get the latest data from the AirNow API.
    try {
      String requestUrl = getRequestUrl(location);

      JSONArray response = Network.getJsonArray(requestUrl);
      if (response == null) {
        return null;
      }

      // Parse the data we are interested in from the response JSON.
      JSONObject forecast = response.getJSONObject(0);
      int aqi = forecast
          .getInt("AQI");
      String category = forecast
          .getJSONObject("Category")
          .getString("Name");
      int categoryNumber = forecast
          .getJSONObject("Category")
          .getInt("Number");

      return new AirData(
          aqi,
          category,
          iconResources.get(categoryNumber)
      );
    } catch (JSONException e) {
      Log.e(TAG, "Failed to parse air quality JSON.", e);
      return null;
    }
  }

  /**
   * Creates the URL for an AirNow API request based on the specified location or {@code null} if
   * the location is unknown.
   */
  private String getRequestUrl(Location location) {
    if (location == null) {
      return null;
    }

    return String.format(
        Locale.US,
        "%s/aq/forecast/latLong/" +
            "?format=application/json" +
            "&latitude=%f" +
            "&longitude=%f" +
            "&API_KEY=%s",
        AIR_NOW_BASE_URL,
        location.getLatitude(),
        location.getLongitude(),
        context.getString(R.string.air_now_api_key));
  }

  @Override
  protected String getTag() {
    return TAG;
  }
}

@@ -2525,27 +2525,84 @@
     
-JSONObject forecast
+for (int i = 0; i %3C response.length(); i++) %7B%0A        JSONObject observation
  = r
@@ -2627,37 +2627,211 @@
 ect(
-0
+i
 );%0A
+%0A  
       
-int aqi = forecast%0A
+// Skip everything but particulate matter observations.%0A        if (!%22PM2.5%22.equals(observation.getString(%22ParameterName%22))) %7B%0A          continue;%0A        %7D%0A%0A        int aqi = observation%0A  
     
@@ -2854,24 +2854,26 @@
 QI%22);%0A      
+  
 String categ
@@ -2878,24 +2878,27 @@
 egory = 
-forecast
+observation
 %0A       
@@ -2892,32 +2892,34 @@
 ation%0A          
+  
 .getJSONObject(%22
@@ -2935,24 +2935,26 @@
 )%0A          
+  
 .getString(%22
@@ -2957,24 +2957,26 @@
 ng(%22Name%22);%0A
+  
       int ca
@@ -2994,17 +2994,21 @@
 r = 
-forecast%0A
+observation%0A 
     
@@ -3005,32 +3005,33 @@
 tion%0A           
+ 
 .getJSONObject(%22
@@ -3033,32 +3033,34 @@
 ect(%22Category%22)%0A
+  
           .getIn
@@ -3075,24 +3075,26 @@
 r%22);%0A%0A      
+  
 return new A
@@ -3115,13 +3115,17 @@
     
+ 
+ 
 aqi,%0A
+  
     
@@ -3140,16 +3140,18 @@
 tegory,%0A
+  
         
@@ -3192,17 +3192,121 @@
 )%0A      
-)
+  );%0A      %7D%0A%0A      Log.e(TAG, %22No particulate matter observation found: %22 + response);%0A      return null
 ;%0A    %7D 
@@ -3729,16 +3729,19 @@
 /aq/
-forecast
+observation
 /lat
@@ -3745,16 +3745,23 @@
 latLong/
+current
 %22 +%0A    

Use air quality observation instead of forecast