
package usda.weru.remoteDataAccess.csip.polygon.prism;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import usda.weru.remoteDataAccess.csip.polygon.CsipInterfacePolygon;
import usda.weru.remoteDataAccess.exceptions.RdaConnectException;
import usda.weru.util.ConfigData;

/**
 *
 * @author mhaas
 */
public class CsipInterfacePrism extends CsipInterfacePolygon {
    
    private static final Logger LOGGER = LogManager.getLogger(CsipInterfacePrism.class);

    CsipInterfacePrism () {
        super();
    }
    
    @Override
    public ArrayList<String> callCsipCatalog () throws RdaConnectException {
        // presently, the catalog / data are all in one call, so do it in the Record call.
        // For now, leave the form, for consistency, even though MOST of the functionality is null.
        ArrayList<String>  ret = new ArrayList<>();
        
        try {
            ret = parseResultCatalog(null);
        } catch (Exception ex) {
            LOGGER.log(Level.INFO, ex.getMessage());
            throw (new RdaConnectException("Unable to connect remote service " + this.interfaceName, ex, this.interfaceName));
        }
        return ret;
    }
    

    @Override
    protected String getCatalogUrl() {
        return ConfigData.getDefault().getData("CD-WS-csip-prism-params-endpoint");
    }
    
    @Override
    protected void addParmsCatalog (JSONObject modelParms) throws JSONException {
        // presently, the catalog / data are all in one call, so do it in the Record call.
    }
    
    @Override
    protected ArrayList<String> parseResultCatalog (JSONObject modelResult) throws JSONException{
        ArrayList<String> retList = new ArrayList<>();
        
        // No sense making name from polygonCenter: it is merely a mouse click
        // in the map.  Thus, it is almost impossible to get exactly the same 
        // lat lon from multiple mouse clicks in the same area...
        // Just use a common name so that the rest of the shared code will work.
        String fName = "prismBlock";
        fName = fName + ".json";
        retList.add(fName);
        return retList;
    }
    
    
    @Override
    public File callCsipGetRecord (String name, String parentPath) throws RdaConnectException {
        JSONObject modelParms;
        JSONObject modelResult;
        File file = null;
        
        this.name = name;
        this.parentPath = parentPath;

        try {
            modelParms = newCsipJson();
            addParmsRecord(modelParms, name, parentPath);
            
            modelResult = doCsipPost(ConfigData.getDefault().getData("CD-WS-csip-prism-params-endpoint"), modelParms);
            file = parseResultRecord(modelResult, name);
            

        } catch (Exception ex) {
            LOGGER.log(Level.INFO, ex.getMessage());
            throw (new RdaConnectException("Unable to get CSIP soil data", ex, this.interfaceName));
        }

        return file;
    }
    
    @Override
    protected void addParmsRecord (JSONObject modelParms, String name, String path) throws JSONException {
        JSONObject parmObj;
        JSONArray jsonParmsArr = modelParms.getJSONArray("parameter");

        if (polygon == null) {
            throw new RuntimeException("polygon not set in LmodCsipIfPrism.addParmsCatalog");
        }
        
        try {
            parmObj = getNewFeatureOBjectBase();
            parmObj.getJSONObject("value").getJSONArray("features").put(getNewGeomFeaturePolygon("polygon 0","0"));
            jsonParmsArr.put(parmObj);
        } catch (JSONException ex) {
            LOGGER.log(Level.ERROR, ex);
        }
    }
    

    @Override
    protected File parseResultRecord (JSONObject modelResult, String recordName) throws JSONException {
        File outFile = null;
        
        try {
            JSONArray resArray = modelResult.getJSONArray("result");
            JSONArray features = resArray.getJSONObject(0).getJSONArray("value");
            
            for (int i = 0; i < features.length(); i++) {
                JSONObject elementObj = features.getJSONObject(i);
                Double lon = elementObj.getJSONArray("center_lon_lat").getDouble(0);
                Double lat = elementObj.getJSONArray("center_lon_lat").getDouble(1);
                String fName = "prismCell";
                fName = fName + lon;
                fName = fName + "." + lat;
                fName = fName + ".json";
                writeResultRecord(elementObj.toString(4), "json", fName);
            }
            
            outFile =  writeResultRecord(features.toString(4), "json", recordName);
        } catch (JSONException ex) {
            LOGGER.log(Level.INFO, ex.getMessage());
        }
       return outFile;
    }
    
    protected File writeResultRecord (String resultStr, String fileExtension, String recordName) throws JSONException {
        try {
            if (!recordName.endsWith(fileExtension)) {
                recordName = recordName + fileExtension;
            }
            File f = new File (destinationPath.toString(), recordName);
            if (!f.exists()) {
                FileOutputStream stream = new FileOutputStream (f);
                stream.write(resultStr.getBytes());
            }
            return f;
        } catch (FileNotFoundException ex) {
            throw (new JSONException("Failed to convert / write LMOD data: cannot find temp file:"+recordName));
        } catch (IOException ex) {
            throw (new JSONException("Failed to convert / write LMOD data: cannot write temp file:"+recordName));
        }
    }    

    
    private JSONObject getNewFeatureOBjectBase () throws JSONException {
        return new JSONObject (
                "{" +
                "\"name\": \"input_zone_features\"," +
                "\"value\": {" +
                "    \"type\": \"FeatureCollection\"," +
                "    \"features\": [" +
                "    ]" +
                "}" +
                "}"
            );
    }
    
    private JSONObject getNewGeomFeaturePolygon (String name, String gidVal) throws JSONException {
        return new JSONObject (
                "{" +
                "        \"type\": \"Feature\"," +
                "        \"properties\": {" +
                "            \"name\": \"" + name + "\"," +
                "            \"gid\": " + gidVal +
                "        }," +
                "        \"geometry\": {" +
                "            \"type\": \"MultiPolygon\"," +
                "            \"coordinates\": [[[" +
                "            [" +
                "                " + polygon.get(0).x + "," +
                "                " + polygon.get(0).y +
                "            ]," +
                "            [" +
                "                " + polygon.get(1).x + "," +
                "                " + polygon.get(1).y +
                "            ]," +
                "            [" +
                "                " + polygon.get(2).x + "," +
                "                " + polygon.get(2).y +
                "            ]," +
                "            [" +
                "                " + polygon.get(3).x + "," +
                "                " + polygon.get(3).y +
                "            ]," +
                "            [" +
                "                " + polygon.get(0).x + "," +
                "                " + polygon.get(0).y +
                "            ]," +
                "            ]]]," +
                "        }" +
                "}"
            );
    }
}
