package org.commcare.util.cli;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.commcare.resources.model.InstallCancelledException;
import org.commcare.resources.model.UnresolvedResourceException;
import org.commcare.util.engine.CommCareConfigEngine;
import org.javarosa.core.util.externalizable.PrototypeFactory;
import org.javarosa.xml.util.UnfullfilledRequirementsException;

public abstract class CliCommand {
    public final String commandName;
    public final String helpTextDescription;
    public final String positionalArgsHelpText;

    protected String[] args;
    protected final Options options;
    protected CommandLine cmd;

    public CliCommand(String commandName, String helpTextDescription, String positionalArgsHelpText) {
        options = getOptions();
        this.commandName = commandName;
        this.helpTextDescription = helpTextDescription;
        this.positionalArgsHelpText = positionalArgsHelpText;
    }

    /**
     * @param args    all the args after (not including) commandName
     */
    public void parseArguments(String[] args) throws ParseException {
        CommandLineParser parser = new DefaultParser();
        cmd = parser.parse(options, args);
        this.args = cmd.getArgs();
    }

    private void checkHelpOption() {
        if (cmd.hasOption("h")) {
            printHelpText();
            System.exit(0);
        }
    }

    public void handle() {
        checkHelpOption();
    }

    protected Options getOptions() {
        Options options = new Options();
        options.addOption(Option.builder("h")
                .desc("Get a list of options")
                .build());
        return options;
    }

    protected void printHelpText() {
        String usage = "java -jar commcare-cli.jar " + commandName + " " + positionalArgsHelpText;
        String header = helpTextDescription + "\n";
        HelpFormatter formatter = new HelpFormatter();
        formatter.setWidth(200);
        formatter.printHelp(usage, header, options, "", true);
    }

    protected static CommCareConfigEngine configureApp(String resourcePath, PrototypeFactory factory) {
        CommCareConfigEngine engine = new CommCareConfigEngine(factory);

        //TODO: check arg for whether it's a local or global file resource and
        //make sure it's absolute
        try {
            if (resourcePath.endsWith(".ccz")) {
                engine.initFromArchive(resourcePath);
            } else {
                engine.initFromLocalFileResource(resourcePath);
            }
            engine.initEnvironment();
            return engine;
        } catch (InstallCancelledException e) {
            System.out.println("Install was cancelled by the user or system");
            e.printStackTrace();
        } catch (UnresolvedResourceException e) {
            System.out.println("While attempting to resolve the necessary resources, one couldn't be found: "
                    + e.getResource().getResourceId());
            e.printStackTrace();
        } catch (UnfullfilledRequirementsException e) {
            System.out.println("While attempting to resolve the necessary resources, a requirement wasn't met");
            e.printStackTrace();
        }
        System.exit(-1);
        return null;
    }
}

@@ -2286,24 +2286,21 @@
 %7D%0A%0A    p
-rotected
+ublic
  static 
@@ -2789,73 +2789,8 @@
   %7D%0A
-            engine.initEnvironment();%0A            return engine;%0A
     
@@ -2934,32 +2934,71 @@
 printStackTrace(
+System.out);%0A            System.exit(-1
 );%0A        %7D cat
@@ -3147,28 +3147,8 @@
 d: %22
-%0A                   
  + e
@@ -3202,32 +3202,71 @@
 printStackTrace(
+System.out);%0A            System.exit(-1
 );%0A        %7D cat
@@ -3451,29 +3451,33 @@
 ckTrace(
+System.out
 );%0A    
-    %7D%0A
         
@@ -3485,32 +3485,76 @@
 ystem.exit(-1);%0A
+        %7D%0A        engine.initEnvironment();%0A
         return n
@@ -3556,12 +3556,14 @@
 urn 
-null
+engine
 ;%0A  

Revert cliCommand to master