/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.felix.gogo.jline;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import org.apache.felix.service.command.CommandSession;
import org.apache.felix.service.command.Function;
import org.apache.felix.service.command.Process;
import org.jline.builtins.Options;

public class Procedural {

    static final String[] functions = {"each", "if", "not", "throw", "try", "until", "while", "break", "continue"};

    public Object _main(CommandSession session, Object[] argv) throws Throwable {
        if (argv == null || argv.length < 1) {
            throw new IllegalArgumentException();
        }
        Process process = Process.Utils.current();
        try {
            return run(session, process, argv);
        } catch (OptionException e) {
            process.err().println(e.getMessage());
            process.error(2);
        } catch (HelpException e) {
            process.err().println(e.getMessage());
            process.error(0);
        } catch (ThrownException e) {
            process.error(1);
            throw e.getCause();
        }
        return null;
    }

    @SuppressWarnings("serial")
    protected static class OptionException extends Exception {
        public OptionException(String message, Throwable cause) {
            super(message, cause);
        }
    }

    @SuppressWarnings("serial")
    protected static class HelpException extends Exception {
        public HelpException(String message) {
            super(message);
        }
    }

    @SuppressWarnings("serial")
    protected static class ThrownException extends Exception {
        public ThrownException(Throwable cause) {
            super(cause);
        }
    }

    @SuppressWarnings("serial")
    protected static class BreakException extends Exception {
    }

    @SuppressWarnings("serial")
    protected static class ContinueException extends Exception {
    }

    protected Options parseOptions(CommandSession session, String[] usage, Object[] argv) throws HelpException, OptionException {
        try {
            Options opt = Options.compile(usage, s -> get(session, s)).parse(argv, true);
            if (opt.isSet("help")) {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                opt.usage(new PrintStream(baos));
                throw new HelpException(baos.toString());
            }
            return opt;
        } catch (IllegalArgumentException e) {
            throw new OptionException(e.getMessage(), e);
        }
    }

    protected String get(CommandSession session, String name) {
        Object o = session.get(name);
        return o != null ? o.toString() : null;
    }

    protected Object run(CommandSession session, Process process, Object[] argv) throws Throwable {
        switch (argv[0].toString()) {
            case "each":
                return doEach(session, process, argv);
            case "if":
                return doIf(session, process, argv);
            case "not":
                return doNot(session, process, argv);
            case "throw":
                return doThrow(session, process, argv);
            case "try":
                return doTry(session, process, argv);
            case "until":
                return doUntil(session, process, argv);
            case "while":
                return doWhile(session, process, argv);
            case "break":
                return doBreak(session, process, argv);
            case "continue":
                return doContinue(session, process, argv);
            default:
                throw new UnsupportedOperationException();
        }
    }

    protected List<Object> doEach(CommandSession session,
                                  Process process,
                                  Object[] argv) throws Exception {
        String[] usage = {
                "each -  loop over the elements",
                "Usage: each [-r] elements [do] { closure }",
                "         elements              an array to iterate on",
                "         closure               a closure to call",
                "  -? --help                    Show help",
                "  -r --result                  Return a list containing each iteration result",
        };
        Options opt = parseOptions(session, usage, argv);

        Collection<Object> elements = getElements(opt);
        if (opt.argObjects().size() > 0 && "do".equals(opt.argObjects().get(0))) {
            opt.argObjects().remove(0);
        }
        List<Function> functions = getFunctions(opt);


        if (elements == null || functions == null || functions.size() != 1) {
            process.err().println("usage: each elements [do] { closure }");
            process.err().println("       elements: an array to iterate on");
            process.err().println("       closure: a function or closure to call");
            process.error(2);
            return null;
        }

        List<Object> args = new ArrayList<>();
        List<Object> results = new ArrayList<>();
        args.add(null);

        for (Object x : elements) {
            checkInterrupt();
            args.set(0, x);
            try {
                results.add(functions.get(0).execute(session, args));
            } catch (BreakException b) {
                break;
            } catch (ContinueException c) {
                // Ignore
            }
        }

        return opt.isSet("result") ? results : null;
    }

    protected Object doIf(CommandSession session, Process process, Object[] argv) throws Exception {
        String[] usage = {
                "if -  if / then / else construct",
                "Usage: if {condition} [then] {if-action} [elif {cond} [then] {elif-action}]... [else] {else-action}",
                "  -? --help                    Show help",
        };
        Options opt = parseOptions(session, usage, argv);

        List<Function> conditions = new ArrayList<>();
        List<Function> actions = new ArrayList<>();
        Function elseFunction = null;
        int step = 0;
        boolean error = false;
        for (Object obj : opt.argObjects()) {
            switch (step) {
                case 0:
                    if (obj instanceof Function) {
                        conditions.add((Function) obj);
                    } else {
                        error = true;
                    }
                    step = 1;
                    break;
                case 1:
                    if ("then".equals(obj)) {
                        step = 2;
                        break;
                    }
                case 2:
                    if (obj instanceof Function) {
                        actions.add((Function) obj);
                        step = 3;
                    } else {
                        error = true;
                    }
                    break;
                case 3:
                    if ("elif".equals(obj)) {
                        step = 4;
                    } else if ("else".equals(obj)) {
                        step = 7;
                    } else if (obj instanceof Function) {
                        elseFunction = (Function) obj;
                        step = 8;
                    } else {
                        error = true;
                    }
                    break;
                case 4:
                    if (obj instanceof Function) {
                        conditions.add((Function) obj);
                    } else {
                        error = true;
                    }
                    step = 5;
                    break;
                case 5:
                    if ("then".equals(obj)) {
                        step = 6;
                        break;
                    }
                case 6:
                    if (obj instanceof Function) {
                        actions.add((Function) obj);
                        step = 3;
                    } else {
                        error = true;
                    }
                    break;
                case 7:
                    if (obj instanceof Function) {
                        elseFunction = (Function) obj;
                        step = 8;
                    } else {
                        error = true;
                    }
                    break;
                case 8:
                    error = true;
                    break;
            }
            if (error) {
                break;
            }
        }
        error |= conditions.isEmpty();
        error |= conditions.size() != actions.size();

        if (error) {
            process.err().println("usage: if {condition} [then] {if-action} [elif {elif-action}]... [else] {else-action}");
            process.error(2);
            return null;
        }
        for (int i = 0, length = conditions.size(); i < length; ++i) {
            if (isTrue(session, conditions.get(i))) {
                return actions.get(i).execute(session, null);
            }
        }
        if (elseFunction != null) {
            return elseFunction.execute(session, null);
        }
        return null;
    }

    protected Boolean doNot(CommandSession session, Process process, Object[] argv) throws Exception {
        String[] usage = {
                "not -  return the opposite condition",
                "Usage: not { condition }",
                "  -? --help                    Show help",
        };
        Options opt = parseOptions(session, usage, argv);
        List<Function> functions = getFunctions(opt);
        if (functions == null || functions.size() != 1) {
            process.err().println("usage: not { condition }");
            process.error(2);
            return null;
        }
        return !isTrue(session, functions.get(0));

    }

    protected Object doThrow(CommandSession session, Process process, Object[] argv) throws ThrownException, HelpException, OptionException {
        String[] usage = {
                "throw -  throw an exception",
                "Usage: throw [ message [ cause ] ]",
                "       throw exception",
                "       throw",
                "  -? --help                    Show help",
        };
        Options opt = parseOptions(session, usage, argv);
        if (opt.argObjects().size() == 0) {
            Object exception = session.get("exception");
            if (exception instanceof Throwable)
                throw new ThrownException((Throwable) exception);
            else
                throw new ThrownException(new Exception());
        }
        else if (opt.argObjects().size() == 1 && opt.argObjects().get(0) instanceof Throwable) {
            throw new ThrownException((Throwable) opt.argObjects().get(0));
        }
        else {
            String message = opt.argObjects().get(0).toString();
            Throwable cause = null;
            if (opt.argObjects().size() > 1) {
                if (opt.argObjects().get(1) instanceof Throwable) {
                    cause = (Throwable) opt.argObjects().get(1);
                }
            }
            throw new ThrownException(new Exception(message, cause));
        }
    }

    protected Object doTry(CommandSession session, Process process, Object[] argv) throws Exception {
        String[] usage = {
                "try -  try / catch / finally construct",
                "Usage: try { try-action } [ [catch] { catch-action } [ [finally] { finally-action } ]  ]",
                "  -? --help                    Show help",
        };
        Options opt = parseOptions(session, usage, argv);
        Function tryAction = null;
        Function catchFunction = null;
        Function finallyFunction = null;
        int step = 0;
        boolean error = false;
        for (Object obj : opt.argObjects()) {
            if (tryAction == null) {
                if (obj instanceof Function) {
                    tryAction = (Function) obj;
                } else {
                    error = true;
                    break;
                }
                step = 1;
            } else if ("catch".equals(obj)) {
                if (step != 1) {
                    error = true;
                    break;
                }
                step = 2;
            } else if ("finally".equals(obj)) {
                if (step != 1 && step != 3) {
                    error = true;
                    break;
                }
                step = 4;
            } else if (step == 1 || step == 2) {
                if (obj instanceof Function) {
                    catchFunction = (Function) obj;
                } else {
                    error = true;
                    break;
                }
                step = 3;
            } else if (step == 3 || step == 4) {
                if (obj instanceof Function) {
                    finallyFunction = (Function) obj;
                } else {
                    error = true;
                    break;
                }
                step = 5;
            } else {
                error = true;
                break;
            }
        }
        error |= tryAction == null;
        error |= catchFunction == null && finallyFunction == null;

        if (error) {
            process.err().println("usage: try { try-action } [ [catch] { catch-action } [ [finally] { finally-action } ] ]");
            process.error(2);
            return null;
        }
        try {
            return tryAction.execute(session, null);
        } catch (BreakException b) {
            throw b;
        } catch (Exception e) {
            session.put("exception", e);
            if (catchFunction != null) {
                catchFunction.execute(session, null);
            }
            return null;
        } finally {
            if (finallyFunction != null) {
                finallyFunction.execute(session, null);
            }
        }
    }

    protected Object doWhile(CommandSession session, Process process, Object[] argv) throws Exception {
        String[] usage = {
                "while -  while loop",
                "Usage: while { condition } [do] { action }",
                "  -? --help                    Show help",
        };
        Options opt = parseOptions(session, usage, argv);
        Function condition = null;
        Function action = null;
        int step = 0;
        boolean error = false;
        for (Object obj : opt.argObjects()) {
            if (condition == null) {
                if (obj instanceof Function) {
                    condition = (Function) obj;
                } else {
                    error = true;
                    break;
                }
                step = 1;
            } else if ("do".equals(obj)) {
                if (step != 1) {
                    error = true;
                    break;
                }
                step = 2;
            } else if (step == 1 || step == 2) {
                if (obj instanceof Function) {
                    action = (Function) obj;
                } else {
                    error = true;
                    break;
                }
                step = 3;
            } else {
                error = true;
                break;
            }
        }
        error |= condition == null;
        error |= action == null;

        if (error) {
            process.err().println("usage: while { condition } [do] { action }");
            process.error(2);
            return null;
        }
        while (isTrue(session, condition)) {
            try {
                action.execute(session, null);
            } catch (BreakException b) {
                break;
            } catch (ContinueException c) {
                // Ignore
            }
        }
        return null;
    }

    protected Object doUntil(CommandSession session, Process process, Object[] argv) throws Exception {
        String[] usage = {
                "until -  until loop",
                "Usage: until { condition } [do] { action }",
                "  -? --help                    Show help",
        };
        Options opt = parseOptions(session, usage, argv);
        Function condition = null;
        Function action = null;
        int step = 0;
        boolean error = false;
        for (Object obj : opt.argObjects()) {
            if (condition == null) {
                if (obj instanceof Function) {
                    condition = (Function) obj;
                } else {
                    error = true;
                    break;
                }
                step = 1;
            } else if ("do".equals(obj)) {
                if (step != 1) {
                    error = true;
                    break;
                }
                step = 2;
            } else if (step == 1 || step == 2) {
                if (obj instanceof Function) {
                    action = (Function) obj;
                } else {
                    error = true;
                    break;
                }
                step = 3;
            } else {
                error = true;
                break;
            }
        }
        error |= condition == null;
        error |= action == null;

        if (error) {
            process.err().println("usage: until { condition } [do] { action }");
            process.error(2);
            return null;
        }
        while (!isTrue(session, condition)) {
            try {
                action.execute(session, null);
            } catch (BreakException e) {
                break;
            } catch (ContinueException c) {
                // Ignore
            }
        }
        return null;
    }

    protected Object doBreak(CommandSession session, Process process, Object[] argv) throws Exception {
        String[] usage = {
                "break -  break from loop",
                "Usage: break",
                "  -? --help                    Show help",
        };
        parseOptions(session, usage, argv);
        throw new BreakException();
    }

    protected Object doContinue(CommandSession session, Process process, Object[] argv) throws Exception {
        String[] usage = {
                "continue -  continue loop",
                "Usage: continue",
                "  -? --help                    Show help",
        };
        parseOptions(session, usage, argv);
        throw new ContinueException();
    }

    private boolean isTrue(CommandSession session, Function function) throws Exception {
        checkInterrupt();
        return isTrue(function.execute(session, null));
    }

    private boolean isTrue(Object result) throws InterruptedException {
        checkInterrupt();

        if (result == null)
            return false;

        if (result instanceof Boolean)
            return (Boolean) result;

        if (result instanceof Number) {
            if (0 == ((Number) result).intValue())
                return false;
        }

        if ("".equals(result))
            return false;

        return !"0".equals(result);
    }

    private void checkInterrupt() throws InterruptedException {
        if (Thread.currentThread().isInterrupted())
            throw new InterruptedException("interrupted");
    }

    @SuppressWarnings("unchecked")
    private Collection<Object> getElements(Options opt) {
        Collection<Object> elements = null;
        if (opt.argObjects().size() > 0) {
            Object o = opt.argObjects().remove(0);
            if (o instanceof Collection) {
                elements = (Collection<Object>) o;
            } else if (o != null && o.getClass().isArray()) {
                elements = Arrays.asList((Object[]) o);
            }
        }
        return elements;
    }

    private List<Function> getFunctions(Options opt) {
        List<Function> functions = new ArrayList<>();
        for (Object o : opt.argObjects()) {
            if (o instanceof Function) {
                functions.add((Function) o);
            }
            else {
                functions = null;
                break;
            }
        }
        return functions;
    }

}
