package com.nutiteq.kml;

import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;

import javax.microedition.lcdui.Image;

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

import com.java4ever.apime.io.GZIP;
import com.nutiteq.cache.Cache;
import com.nutiteq.components.ExtendedDataMap;
import com.nutiteq.components.KmlPlace;
import com.nutiteq.components.WgsPoint;
import com.nutiteq.io.ResourceDataWaiter;
import com.nutiteq.io.ResourceRequestor;
import com.nutiteq.log.Log;

/**
 * Creates KML Elements from JSON data. Specific for CloudMade geocoder
 * @author Jaak Laineste
 *
 */
public class JsonKmlReader implements ResourceRequestor, ResourceDataWaiter {

  private static Image defaultKmlIcon = Image.createImage(18, 18);

  private final KmlService service;
  private final KmlElementsWaiter servicesHandler;
  private final String serviceUrl;
  private int placeCount;
  private static final String DEFAULT_KML_ICON = "/images/def_kml.png";

  public JsonKmlReader(final KmlElementsWaiter servicesHandler, final KmlService service,
          final String serviceUrl){
      this(servicesHandler, service, serviceUrl, DEFAULT_KML_ICON);
  }
  
  public JsonKmlReader(final KmlElementsWaiter servicesHandler, final KmlService service,
      final String serviceUrl, final String defaultIcon) {
    this.servicesHandler = servicesHandler;
    this.service = service;
    this.serviceUrl = serviceUrl;

      try {
        defaultKmlIcon = Image.createImage(defaultIcon);
      } catch (final IOException e) {
        defaultKmlIcon = Image.createImage(18, 18);
      }

  }

  public String resourcePath() {
    return serviceUrl;
  }

  public void dataRetrieved(final byte[] data) {
    boolean guessPacked = false;
    if(data[0]==31 && data[1]==-117){
        guessPacked=true;
        Log.debug("Guess response packed based on first 2 data bytes"); 
    }else{
        Log.debug("Response NOT packed based on first 2 data bytes");
    }
        
      
//      Log.debug("KmlReader.read() response packed ? " + responsePacked + ". Bytes:"+data.length);
    final byte[] finalData = guessPacked ? GZIP.inflate(data) : data;
    // remove BOM (ie the first 3 bytes)
    if(finalData[0]==0xef && finalData[1]==0xbb && finalData[2]==0xbf){
        System.arraycopy(finalData, 3, finalData, 0, finalData.length-3);
    }
        

    try {
      servicesHandler.addKmlPlaces(service, read(finalData, service.maxResults()));
    } catch (final IOException e) {
      Log.printStackTrace(e);
      notifyError();
    } finally {
    }
    Log.debug("JsonKmlReader done, read places: "+placeCount);
    
  }

  public void notifyError() {
    //TODO jaanus : ignore?
  }

  protected KmlPlace[] read(final byte[] finalData, final int maxResults) throws IOException {

    final Vector places = new Vector();
// read JSON and create KmlPlace from it.
    
    String jsonString = new String(finalData,"UTF8");
    ExtendedDataMap xdata = new ExtendedDataMap();
    
    try {
        JSONObject root = new JSONObject(jsonString);
        int found = root.getInt("found");
        Log.debug("found "+found+" objects");
        JSONArray features = root.getJSONArray("features");

        int size = features.length();
        
        for (int i=0;i<size;i++){
            JSONObject feature = (JSONObject) features.get(i);

            JSONObject location = feature.optJSONObject("location");
            String country = location.getString("country");
            String county = location.getString("county");

            JSONObject properties = feature.optJSONObject("properties");
            String placeType = properties.getString("place");
            String name = properties.getString("name");
            
            JSONObject centroid = feature.optJSONObject("centroid");
            JSONArray coordinates = centroid.optJSONArray("coordinates");

            String latS = coordinates.getString(0);
            String lngS = coordinates.getString(1);

            double lat = Double.parseDouble(latS);
            double lng = Double.parseDouble(lngS);

            for (Enumeration e = properties.keys() ; e.hasMoreElements() ;) {
                String key = (String) e.nextElement();
                String val = properties.getString(key);
                xdata.addPair(key, val);
            }

            xdata.addPair("country", country);
            xdata.addPair("county", county);
            xdata.addPair("place", placeType);

        // create KML object

            KmlPlace place = new KmlPlace(name, defaultKmlIcon, new WgsPoint(lng,lat), null, placeType+" in "+county+", "+country, null, null, xdata);
            places.addElement(place);
            
        
        } // for each feature found
        
    } catch (JSONException e) {
        e.printStackTrace();
        notifyError();
    }

    
    // TODO now some dummy place for testing

    
    final KmlPlace[] result = new KmlPlace[places.size()];
    places.copyInto(result);
    placeCount = places.size();
    return result;
  }

  public int getCachingLevel() {
    return Cache.CACHE_LEVEL_NONE;
  }
}

