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;

import vo.parameter.*;

public class JsonEncoderMerge
{


   @SuppressWarnings("unchecked")
   private static JSONObject coordinatesToJsonObj(Coord coord)
   {
      JSONObject obj = new JSONObject();

      obj.put("skysystem",  coord.skySystem);
      obj.put("shape",      coord.pos.shape);
      obj.put("specsystem", coord.specSystem);

      /* SODA */

      if(coord.pos != null)
      {
         obj.put("pos", objJPos(coord.pos));
      }

      if(coord.band != null)
      {
         obj.put("band", arrJBand(coord.band));
      }

      if(coord.time != null)
      {
         obj.put("time", genTimeJsonArr(coord.time) );
      }

      if(coord.pol != null)
      {
         obj.put("pol", genPolJsonArr(coord.pol) );
      }

      return obj;
   }


   private static 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 static 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 static JSONObject objJPolygon(Polygon poly)
   {
      JSONObject obj = new JSONObject();
      obj.put("lon", genPolyLonJsonArr(poly));
      obj.put("lat", genPolyLatJsonArr(poly));
      return obj;
   }

   private static JSONObject objJPos(Pos pos)
   {
      JSONObject obj = new JSONObject();
      if(pos.circle  != null) obj.put("circle",  objJCircle(pos.circle));
      if(pos.range   != null) obj.put("range",   objJRange(pos.range));
      if(pos.polygon != null) obj.put("polygon", objJPolygon(pos.polygon));
      return obj;
   }

   private static JSONArray arrJBand(Band band)
   {
      JSONArray arr = new JSONArray();
      arr.add(band.getMin());
      arr.add(band.getMax());
      return arr;
   }

   private static JSONArray genTimeJsonArr(Time time)
   {
      JSONArray arr = new JSONArray();
      arr.add(time.getMin());
      arr.add(time.getMax());
      return arr;
   }

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



   private static JSONArray genPolJsonArr(Pol pol)
   {
      JSONArray jarr = new JSONArray();
      for(String str : pol.states) jarr.add(str);
      return jarr;
   }


   private static JSONArray extraCardsToJson(FitsCard[] extraCards)
   {
      JSONArray jcards = new JSONArray();
      for(FitsCard card : extraCards)
      {
         //jcards.add(card); FIXME check what would this add; compiler did not complain

         JSONObject jcard = new JSONObject();
         jcard.put("key", card.key);
         jcard.put("value", card.value);
         jcard.put("comment", card.comment);

         jcards.add(jcard);
      }
      return jcards;
   }





   @SuppressWarnings("unchecked")
   public static String subimgToJson(
         String imgPathname,
         int imgHdunum,
         Coord coord,
         String subimgFilename,
         FitsCard[] extraCards,
         boolean countNullValues)
   {
      JSONObject obj = new JSONObject();

      obj.put("service",  "SUBIMG");

      obj.put("img_pathname",    imgPathname);
      obj.put("img_hdunum",      imgHdunum);
      obj.put("coordinates",     coordinatesToJsonObj(coord));
      obj.put("subimg_filename", subimgFilename);

      if((extraCards != null) && (extraCards.length > 0))
      {
         obj.put("extra_cards", extraCardsToJson(extraCards));
      }

      obj.put("count_null_values", countNullValues);

      return obj.toJSONString();
   }



   @SuppressWarnings("unchecked")
   public static String mergefilesToJson(
         String dimensionality, 
         String[] filestomerge )
   {
      JSONObject objParameters = new JSONObject();
      objParameters.put("dimensionality", dimensionality);

      JSONArray fnames = new JSONArray();
      for(String fn : filestomerge){
         fnames.add(fn);
      }
      objParameters.put("files_to_merge", fnames);

      JSONObject obj = new JSONObject();
      obj.put("service",  "MERGEF");
      obj.put("parameters",  objParameters);

      return obj.toJSONString();
   }



   // BEGIN merge-parallel

   @SuppressWarnings("unchecked")
   public static String mergefilesCommonHeaderToJson(
         String jobId,
         String dimensionality, 
         String[] filestomerge )
   {
      JSONObject objParameters = new JSONObject();
      objParameters.put("merge_id", jobId);
      objParameters.put("dimensionality", dimensionality);

      JSONArray fnames = new JSONArray();
      for(String fn : filestomerge){
         fnames.add(fn);
      }
      objParameters.put("files_to_merge", fnames);

      JSONObject obj = new JSONObject();
      obj.put("service",  "MERGE1"); // MERGE phase 1: create common header
      obj.put("parameters",  objParameters);


      return obj.toJSONString();
   }

   @SuppressWarnings("unchecked")
   public static String mergefilesReprojectToJson(
         String jobId,
         String dimensionality, 
         String fitsFileName)
   {
      JSONObject objParameters = new JSONObject();
      objParameters.put("merge_id", jobId);
      objParameters.put("dimensionality", dimensionality);
      objParameters.put("fits_filename", fitsFileName);

      JSONObject obj = new JSONObject();
      obj.put("service",  "MERGE2"); // MERGE phase 2: reproject one fitsfile
      obj.put("parameters",  objParameters);

      return obj.toJSONString();
   }

   @SuppressWarnings("unchecked")
   public static String mergefilesAddReprojectedToJson(
         String jobId,
         String dimensionality )
   {
      JSONObject objParameters = new JSONObject();
      objParameters.put("merge_id", jobId);
      objParameters.put("dimensionality", dimensionality);

      JSONObject obj = new JSONObject();
      obj.put("service",  "MERGE3"); // MERGE phase 3: add all reprojected files
      obj.put("parameters",  objParameters);

      return obj.toJSONString();
   }

   // END merge-parallel


}