
/*
 *  Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
*/
package oracle.sample;

import java.util.*;
import java.util.logging.Logger;

/**
 * <p>
 * </p>
 *
 * @author velsubra
 */
public class StringUtils {
    static final char quote = '\"';

    static final Logger logger = Logger.getLogger(StringUtils.class.getName());


    public static String commandToScript(String cmd, String dir) {
        if (!dir.startsWith("/")) {
            dir = "/" + dir;
        }
        String script = "import org.unix4j.*;\n" +
                "import org.unix4j.ls.*;\n" +
                "import org.unix4j.unix.*;\n" +
                "import oracle.sample.*;\n" +
                "import org.unix4j.context.*;\n" +
                "\nunix_context_factory = new Unix4JExecutionContextFactory(\"" + dir + "\");";


        script += "\nunix = Unix4j.use(unix_context_factory);";
        script += "\nunix_pwd = new PwdLineOperation();";
        script += "\nunix_out = " + StringUtils.expressionToCall("unix", cmd) + ".join(unix_pwd).toStringResult();";
        script += "\npwd = unix_pwd.getPwd();";
        script += "\nreturn unix_out ";

        return script;
    }


    public static List<String> parse(String input, String with) {
        List<String> ret = new ArrayList<String>();
        if (input == null) return ret;
        int index_D = findIndexOf(with, input);

        while (index_D >= 0) {
            logger.fine("Remaining:" + input);
            String text = input.substring(0, index_D);
            if (text.length() > 0) {
                ret.add(text);
            }
            input = input.substring(index_D + with.length(), input.length());

            index_D = findIndexOf(with, input);
        }
        logger.fine("Finally remaining:" + input);
        if (!input.trim().equals("")) {
            ret.add(input);
        }

        return ret;
    }


    public static String expressionToCall(String ref, String input) {
        if (input == null) input = "";
        List<String> cmds = parse(input, "|");
        StringBuffer script = new StringBuffer(ref);
        for (String cmd : cmds) {
            String method = commandToCall(cmd);
            if (!method.trim().equals("")) {
                script.append(".");
                script.append(method);
            }
        }
        return script.toString();

    }

    public static String capitalizeFirstLetter(String cmd) {
        return cmd.substring(0, 1).toUpperCase() + cmd.substring(1, cmd.length());
    }

    public static String commandToCall(String cmd) {
        List<String> single = parse(cmd.trim(), " ");
        if (single.isEmpty()) {
            return "";
        }
        if (single.size() > 0) {

            List<String> args = new ArrayList<String>();
            Set<String> options = new HashSet<String>();
            for (int i = 1; i < single.size(); i++) {
                String arg = single.get(i).trim();
                if (arg.equals("")) continue;
                if (arg.startsWith("-")) {
                    if (arg.length() > 0) {
                        for (int j = 1; j < arg.length(); j++) {
                            options.add(String.valueOf(arg.charAt(j)));
                        }
                    }
                } else {
                    if (arg.startsWith(String.valueOf(quote)) && arg.endsWith(String.valueOf(quote))) {
                        arg = arg.substring(1, arg.length() - 1);
                    }
                    //escape
                    args.add(escapeString(arg));
                }


            }
            StringBuffer ex = new StringBuffer(single.get(0));
            ex.append("(");
            if (!options.isEmpty()) {
                ex.append(capitalizeFirstLetter(single.get(0)) + ".Options." + getSeparatedListOfString(options, "", "", false, "."));
                if (!args.isEmpty()) {
                    ex.append(",");
                }
            }
            if (!args.isEmpty()) {
                ex.append(getSeparatedListOfString(args, "", "", true, ","));
            }
            ex.append(")");
            return ex.toString();
        } else {
            if (single.get(0).trim().equals("")) {
                return "";
            } else {
                return single.get(0) + "()";
            }
        }
    }

    public static String escapeString(String s) {
        if (s == null)
            return null;
        StringBuffer builder = new StringBuffer("");
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '\"') {
                builder.append("\\\"");
            } else if (s.charAt(i) == '\\') {
                builder.append("\\\\");
            } else if (s.charAt(i) == '\n') {
                builder.append("\\n");
            } else {
                builder.append(s.charAt(i));
            }

        }
        return builder.toString();

    }

    public static String getCommaSeparatedListOfString(String[] list) {
        if (list == null)
            return null;
        return getCommaSeparatedListOfString(Arrays.asList(list));
    }

    public static String getCommaSeparatedListOfString(Collection<String> list) {
        return getCommaSeparatedListOfString(list, "(", ")", true);
    }

    public static String getSimpleCommaSeparatedListOfString(String[] list) {
        if (list == null)
            return null;
        return getCommaSeparatedListOfString(list, "", "", false);
    }


    public static String getCommaSeparatedListOfString(String[] list, String open, String close,
                                                       boolean singleQuoteElement) {
        List<String> listStr = null;
        if (list != null) {
            listStr = Arrays.asList(list);
        }
        return getCommaSeparatedListOfString(listStr, open, close, singleQuoteElement);

    }

    public static String getCommaSeparatedListOfString(Collection<String> list, String open, String close,
                                                       boolean singleQuoteElement) {
        return getSeparatedListOfString(list, open, close, singleQuoteElement, ",");
    }

    public static String getSeparatedListOfString(Collection<String> list, String open, String close,
                                                  boolean singleQuoteElement, String separator) {
        if (list == null)
            return null;
        StringBuffer buffer = new StringBuffer(open);
        for (Iterator<String> it = list.iterator(); it.hasNext(); ) {
            String item = it.next();
            if (singleQuoteElement) {
                buffer.append(quote + item + quote);
            } else {
                buffer.append(item);
            }
            if (it.hasNext()) {
                buffer.append(separator);
            }
        }
        buffer.append(close);
        return buffer.toString();
    }

    public static int findIndexOf(String what, String where) {
        if (where == null || what == null) return -1;
        boolean insideQuote = false;
        boolean escaping = false;

        for (int i = 0; i < where.length(); i++) {
            if (where.length() - i < what.length()) {
                return -1;
            }
            char c = where.charAt(i);
            switch (c) {
                case '\\':
                    escaping = !escaping;
                    break;

                case quote:
                    if (!escaping) {
                        insideQuote = !insideQuote;
                    }
                    escaping = false;
                    break;
                default:


                    if (!insideQuote) {
                        if (where.substring(i, where.length()).startsWith(what)) {
                            return i;
                        }
                    }
                    escaping = false;
                    break;

            }

        }
        return -1;

    }
}
