
package usda.weru.remoteDataAccess.csip.crlmod;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import usda.weru.remoteDataAccess.csip.CsipInterface;
import usda.weru.remoteDataAccess.exceptions.RdaConnectException;
import usda.weru.util.ConfigData;

/**
 *
 * @author mhaas
 */
public abstract class CsipInterfaceCrLmod extends CsipInterface {
    
    int retryCount;
    
    CsipInterfaceCrLmod () {
        super();
        
        retryCount = 0;
        String cacheParm = ConfigData.getDefault().getData("CD-WS-Csip-lmod-RetryCnt");
        if (cacheParm != null) {
            retryCount = Integer.valueOf(cacheParm);
        }
    }
    
    @Override
    protected void addParmsCatalog (JSONObject modelParms) throws JSONException {
        
    }
    
    // The sub-classes then fill in the variable parameters, and call back to this code.
    protected File callGetRecordLmod (String Url, String name, String parentPath) throws RdaConnectException {
        return callGetRecordLmod (Url, name, parentPath, true);
    }
    protected File callGetRecordLmod (String Url, String name, String parentPath, boolean stripName) throws RdaConnectException {
        JSONObject modelParms;
        JSONObject modelResult;
        String localName;
        File file = null;
        Exception exSave = null;
        String modelResultSave = "";
        
        try {
            modelResult = new JSONObject();
            modelParms = newCsipJson();
            addParmsRecord(modelParms, name, parentPath, stripName);

            // slashes (in a filename, not the path ...) make creating a new file gag. Not suprising. nice file names...
            // need 4 to escape it twice, once for java, and once more for regex
            // do the name fix here, so that it only affects the local filename creation
            localName = name.replaceAll("\\\\", "");
            localName = localName.replaceAll("/", "");

            for (int i=0; i<retryCount; i++) {
                try {
                    modelResult = doCsipPost(Url, modelParms);
                    file = parseResultRecord (modelResult, localName);
                    return file;
                } catch (Exception ex) {
                    exSave = ex;
                    modelResultSave = modelResult.toString(4);
                }
            }
            throw (exSave);
        
        } catch (Exception ex) {
            Logger.getLogger(this.getClass().getName()).log(Level.INFO, ex.getMessage());
            Logger.getLogger(this.getClass().getName()).log(Level.INFO, "    result: " + modelResultSave);
            throw (new RdaConnectException("Unable to get Lmod data", ex, this.interfaceName));
        }
    }
    
    @Override
    protected void addParmsRecord (JSONObject modelParms, String name, String path) throws JSONException {
        addParmsRecord(modelParms, name, path, true);
    }

    protected void addParmsRecord (JSONObject modelParms, String name, String path, boolean stripName) throws JSONException {
        JSONArray jsonParmsArr = modelParms.getJSONArray("parameter");
        
        String crLmodGetType="name";  // types of CrLmod gets: name, keywords (also possible: path, id)
        
        if (name.contains("'")) {
            // sql escape of single quote is to double it
            name=name.replace("'", "''");
         }
        
//        name=name.trim();
//        
//        if (stripName && (name.contains(" - ") || name.contains("--"))) {
//            // a standalone hyphen in the name makes the csip call gag. Not suprising. nice file names...
//            // do the name fix here, so that it only affects the CSIP call
//            name = name.replaceAll(" - ", " ");
//            name = name.replaceAll("--", " ");
//            crLmodGetType="keywords";
//        }
//        
//        if (name.contains("/")) {
//            // sometimes the substitution in crlmod substitutes "and" other times substitutes " "
//            // use space and then do a keyword search instead of name search
//            //name=name.replace("/", " and ");
//            name=name.replace("/", " ");
//            crLmodGetType="keywords";
//        }
//        
//        if (name.contains("'")) {
//            name=name.replaceAll("[0-9]*'", " ");
//            // if the above didn't get it, just subst the char. only
//            name=name.replace("'", " ");
//            crLmodGetType="keywords";
//        }
//        
//        if (name.contains(".")) {
//            name=name.replace(".", " ");
//            crLmodGetType="keywords";
//        }
//        
//        if (name.contains("@")) {
//            name=name.replace("@", " ");
//            crLmodGetType="keywords";
//        }
//        
//        if (name.contains("%")) {
//            name=name.replace("%", " ");
//            crLmodGetType="keywords";
//        }
//        
//        if (name.contains(":")) {
//            name=name.replace(":", " ");
//            crLmodGetType="keywords";
//        }
//        
////        if (name.matches(".*[0-9][xX].*")) {
////            int iii = 1;
////        }
////        
////        if (name.matches(".*[0-9]x.*")) {
////            name = name.replaceAll("[0-9]*x", " ");
////            crLmodGetType="keywords";
////        }
////        
////        if (name.matches(".*[0-9]X.*")) {
////            name = name.replaceAll("[0-9]*X", " ");
////            crLmodGetType="keywords";
////        }
        
//        jsonParmsArr.put(new JSONObject().put("name","name").put("value",new JSONArray().put(name)) );
        if (crLmodGetType.contentEquals("name")) {
            jsonParmsArr.put(new JSONObject().put("name",crLmodGetType).put("value",new JSONArray().put(name)) );
        } else if (crLmodGetType.contentEquals("keywords")) {
            
            while(name.contains("  ")) {
                name=name.replace("  ", " ");
            }
            while(name.contains(" , ")) {
                name=name.replace(" , ", " ");
            }
            jsonParmsArr.put(new JSONObject().put("name",crLmodGetType).put("value",name) );
        }
        
        if (path.endsWith("\\")) {
            path = path.substring(0, path.length()-2);
        }
        jsonParmsArr.put(new JSONObject().put("name","path").put("value",new JSONArray().put(path)) );
        
        jsonParmsArr.put(new JSONObject().put("name","native_formats").put("value","true") );
        jsonParmsArr.put(new JSONObject().put("name","format").put("value","weps") );
    }
    
    // This is the call used by any invoking functions and is implemented in the sub-classes
    // protected abstract File parseResultRecord (JSONObject modelResults, String recordName) throws JSONException;
    
    // The sub-classes then fill in the variable parameters, and call back to this code.
    // NOTE: same name, additional parms in parameter list.
    protected File parseResultRecordLmod (JSONObject modelResults, String serviceName, String fileExtension, String recordName, String csipDataParmName) throws JSONException {
        JSONObject resultObject;
        String resultStr;
        
        try {
            resultObject = modelResults.getJSONArray("result").getJSONObject(0);
            resultStr = resultObject.getJSONObject("value").getJSONArray(serviceName).getJSONObject(0).getString(csipDataParmName);

            return writeResultRecordLmod(resultStr, fileExtension, recordName);
        } catch (JSONException ex) {
            // do logging in the caller.
            //Logger.getLogger(this.getClass().getName()).log(Level.INFO, "JSON error: " + ex.getMessage());
            //Logger.getLogger(this.getClass().getName()).log(Level.INFO, "    result: " + modelResults.toString(4));
        }
        throw (new JSONException("Failed to convert / write LMOD data: unexpected Lmod data"));
    }
    
    
    protected File writeResultRecordLmod (String resultStr, String fileExtension, String recordName) throws JSONException {
        try {
            if (!recordName.endsWith(fileExtension)) {
                recordName = recordName + fileExtension;
            }
            File f = new File (destinationPath.toString(), recordName);
            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));
        }
    }    
}
