
package usda.weru.remoteDataAccess.csip;

import csip.utils.Client;
import csip.utils.JSONUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
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.RdaInterface;
import usda.weru.remoteDataAccess.exceptions.RdaConnectException;

/**
 *
 * @author mhaas
 */
public abstract class CsipInterface extends RdaInterface {

    Logger LOGGER = LogManager.getLogger(CsipInterface.class);
    protected Client client;

    public CsipInterface() {
        //client = new Client(null);
        // Client need a java logger
        java.util.logging.Logger clientLog = java.util.logging.Logger.getLogger(CsipInterface.class.getName());
        clientLog.setLevel(java.util.logging.Level.WARNING);
        client = new Client(clientLog);
    }

    protected abstract void addParmsCatalog(JSONObject modelParms) throws JSONException;

    public abstract ArrayList<String> callCsipCatalog() throws RdaConnectException;

    protected abstract ArrayList<String> parseResultCatalog(JSONObject modelResult) throws JSONException;

    protected abstract void addParmsRecord(JSONObject modelParms, String name, String path) throws JSONException;

    public abstract File callCsipGetRecord(String name, String parentPath) throws RdaConnectException;

    protected abstract File parseResultRecord(JSONObject modelResults, String recordName) throws JSONException;
    

    
    protected ArrayList<String> formatResults(JSONObject modelResult, int tabAmt) {
        ArrayList<String> lines = new ArrayList<>();
        String tab = "                      ".substring(0, tabAmt);
        lines.add("{" + "\n");
        lines.addAll(formatObjectRecurse(modelResult, tab, ""));
        lines.add("}" + "\n");
        return lines;
    }

    protected JSONObject newCsipJson() throws JSONException {
        JSONObject modelParms = new JSONObject();

        modelParms.put("metainfo", new JSONObject());
        modelParms.put("parameter", new JSONArray());

        return (modelParms);
    }

    protected ArrayList<String> formatObjectRecurse(JSONObject jsonObject, String tabBase, String tab) {
        ArrayList<String> lines = new ArrayList<>();
        ArrayList<String> resLines;
        String key;
        Object o;
        String line;

        try {
            tab += tabBase;

            Iterator<?> keys = jsonObject.keys();
            while (keys.hasNext()) {
                o = keys.next();
                if (o instanceof String) {
                    key = (String) o;
                    line = tab + key + ": ";
                    o = jsonObject.get(key);
                    if (o instanceof JSONObject) {
                        resLines = formatObjectRecurse((JSONObject) o, tabBase, tab);
                        if (resLines.size() > 0) {
                            lines.add(line + "{" + "\n");
                            lines.addAll(resLines);
                            lines.add(tab + "}," + "\n");
                        } else {
                            lines.add(line + "{" + "}," + "\n");
                        }
                    } else if (o instanceof JSONArray) {
                        resLines = formatArrayRecurse((JSONArray) o, tabBase, tab);
                        if (resLines.size() > 0) {
                            lines.add(line + "[" + "\n");
                            lines.addAll(resLines);
                            lines.add(tab + "]," + "\n");
                        } else {
                            lines.add(line + "[" + "]," + "\n");
                        }
                    } else {
                        lines.add(line + o.toString() + ",\n");
                    }
                }
            }
        } catch (JSONException ex) {
            LOGGER.log(Level.INFO, ex.getMessage());
        }

        return lines;
    }

    protected ArrayList<String> formatArrayRecurse(JSONArray jsonArray, String tabBase, String tab) {
        ArrayList<String> lines = new ArrayList<>();
        ArrayList<String> resLines;
        String key;
        Object o;
        String line;

        try {
            tab += tabBase;

            for (int i = 0; i < jsonArray.length(); i++) {
                o = jsonArray.get(i);
                if (o.getClass() == JSONObject.class) {
                    resLines = formatObjectRecurse((JSONObject) o, tabBase, tab);
                    if (resLines.size() > 0) {
                        lines.add(tab + "{" + "\n");
                        lines.addAll(resLines);
                        lines.add(tab + "}," + "\n");
                    } else {
                        lines.add(tab + "{" + "}," + "\n");
                    }
                } else if (o.getClass() == JSONArray.class) {
                    resLines = formatArrayRecurse((JSONArray) o, tabBase, tab);
                    if (resLines.size() > 0) {
                        lines.add(tab + "[" + "\n");
                        lines.addAll(resLines);
                        lines.add(tab + "]," + "\n");
                    } else {
                        lines.add(tab + "[" + "]," + "\n");
                    }
                } else {
                    lines.add(tab + o.toString() + ",\n");
                }
            }
        } catch (JSONException ex) {
            LOGGER.log(Level.INFO, ex.getMessage());
        }

        return lines;
    }

    //
    // Copied from csip-core package
    //        from file ServiceTest.java ( Method download() )
    //
    // MEH: added return of stdout & stderr names
    //

    /**
     *  Copied from csip-core package from file ServiceTest.java : download()
     * 
     *  MEH: added return of stout &stderr names.
     * 
     *  url might have %20 in it.
     *  Need to leave %20 there when passing it to the CSIP client functions
     *  in order for it to match.
     *  But when doing formatting check, replace it with space.
     * 
     * @param resp - JSON object containing results
     * @param resultFolder - folder to output results
     * @return 
     */
    protected File downloadCsipResults(JSONObject resp, File resultFolder) {
        File out = null;
        
        try {
            JSONArray arr = resp.getJSONArray("result");
            Map<String, JSONObject> rmap = JSONUtils.preprocess(arr);
            
            for (String key : rmap.keySet()) {
                JSONObject val = rmap.get(key);
                String url = val.getString("value");
                
                String checkURL = url;
                checkURL = checkURL.replace("%20", " ");
                
                if (checkURL.startsWith("http") && checkURL.contains("/q/") && checkURL.endsWith(key)) {
                    if(!resultFolder.exists()) {
                        resultFolder.mkdir();
                    }
                    
                    out = new File(resultFolder, key);
                    try {
                        client.doGET(url, out);
                    } catch(Exception e) {
                        System.err.println("Missing output file: " + key);
                    }
                } else {
                    System.err.println("Bad URL in result: " + url);
                }
            }
            
        } catch(JSONException je) {
            System.err.println("Error at downloadCsipResults - " + je.getMessage());
        }
        
        return out;
    }

    protected JSONObject doCsipPost(String modelUrl, JSONObject modelParms) throws Exception {

        JSONObject modelResult = client.doPOST(modelUrl, modelParms);
        return (modelResult);
    }
}
