
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.Iterator;
/* 'JSON-Simple' library */
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;


public class JsonEncoder
{
   static final Logger LOGGER = Logger.getLogger("JsonEncoder");

   private JSONObject obj;

   public JsonEncoder() { this.obj = new JSONObject(); this.obj.put("service","SUBIMG"); }

   public String toString() { return this.obj.toString(); }


   public void add(String pathname, int hdunum)
   {
      LOGGER.info("trace" + pathname);

      this.obj.put("img_pathname", pathname);
      this.obj.put("img_hdunum",   hdunum);
   }


   // NOTE: implementation of NULL: do not put into json
   // (alternatively could put JSON.NULL as "pos" value or use pos.system.NONE)

   public void add(Pos pos)
   {
      if(pos != null)
      {
         JSONObject j = new JSONObject();
         j.put("system", pos.system.toString());

         if(pos.circle  != null) j.put("circle",  objJCircle(pos.circle));
         if(pos.range   != null) j.put("range",   objJRange(pos.range));
         if(pos.polygon != null) j.put("polygon", objJPolygon(pos.polygon));

         this.obj.put("pos", j);
      }
   }


   public void add(Band band)
   {
      if(band != null)
      {
         JSONObject j = new JSONObject();
         j.put("system", band.system.toString());

         JSONArray arr = new JSONArray();
         for(double dbl : band.wavelength) arr.add(dbl);
         j.put("interval",arr);

         this.obj.put("band", j);
      }
   }


   public void add(Time time)
   {
      if(time != null)
      {
         JSONObject j = new JSONObject();
         j.put("system", time.system.toString());

         JSONArray arr = new JSONArray();
         for(double dbl : time.mjdUtc) arr.add(dbl);
         j.put("interval",arr);

         this.obj.put("time", j);
      }
   }


   public void add(Pol pol)
   {
      if(pol != null)
      {
         JSONArray arr = new JSONArray();
         for(String val : pol.states) arr.add(val);
         this.obj.put("pol",arr);
      }
   }


   public void add(FitsCard[] extraCards)
   {
      if((extraCards != null) && (extraCards.length > 0)) 
      {
         obj.put("extra_cards", extraCardsToJson(extraCards));
      }
   }


   public void add(boolean countNullValues)
   {
      obj.put("count_null_values", countNullValues);
   }



   private JSONArray extraCardsToJson(FitsCard[] extraCards)
   {
      JSONArray jcards = new JSONArray();
      for(FitsCard card : extraCards)
      {
         JSONObject j = new JSONObject();
         j.put("key",     card.key);
         j.put("value",   card.value);
         j.put("comment", card.comment);
         jcards.add(j);
      }
      return jcards;
   }


   private JSONObject objJCircle(Circle circle)
   {
      JSONObject obj = new JSONObject();
      obj.put("lon", circle.lon);
      obj.put("lat", circle.lat);
      obj.put("radius", circle.radius);
      return obj;
   }


   private JSONObject objJRange(Range range)
   {
      JSONObject obj = new JSONObject();
      obj.put("lon1", range.lon1);
      obj.put("lon2", range.lon2);
      obj.put("lat1", range.lat1);
      obj.put("lat2", range.lat2);
      return obj;
   }

   private JSONObject objJPolygon(Polygon poly)
   {
      JSONObject obj = new JSONObject();
      obj.put("lon", genPolyLonJsonArr(poly));
      obj.put("lat", genPolyLatJsonArr(poly));
      return obj;
   }


   private JSONArray genPolyLonJsonArr(Polygon polygon)
   {
      JSONArray jarr = new JSONArray();
      for(double dbl : polygon.lon) jarr.add(dbl);
      return jarr;
   }


   private JSONArray genPolyLatJsonArr(Polygon polygon)
   {
      JSONArray jarr = new JSONArray();
      for(double dbl : polygon.lat) jarr.add(dbl);
      return jarr;
   }

}

