/*
 * 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.sling.pipes.internal;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.security.AccessControlException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.servlets.ServletResolverConstants;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.pipes.CommandExecutor;
import org.apache.sling.pipes.ExecutionResult;
import org.apache.sling.pipes.OutputWriter;
import org.apache.sling.pipes.Pipe;
import org.apache.sling.pipes.PipeBuilder;
import org.apache.sling.pipes.PipeExecutor;
import org.apache.sling.pipes.Plumber;
import org.jetbrains.annotations.NotNull;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import static org.apache.sling.pipes.PipeBindings.INJECTED_SCRIPT_REGEXP;
import static org.apache.sling.pipes.internal.CommandUtil.writeToMap;

import javax.servlet.Servlet;
import javax.servlet.ServletException;

@Component(service = {Servlet.class, CommandExecutor.class}, property= {
    ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES + "=" + CommandExecutorImpl.RESOURCE_TYPE,
    ServletResolverConstants.SLING_SERVLET_METHODS + "=POST",
    ServletResolverConstants.SLING_SERVLET_EXTENSIONS + "=txt"
})
public class CommandExecutorImpl extends SlingAllMethodsServlet implements CommandExecutor {
    final Logger log = LoggerFactory.getLogger(CommandExecutorImpl.class);
    public static final String RESOURCE_TYPE = "slingPipes/exec";
    static final String REQ_PARAM_FILE = "pipe_cmdfile";
    static final String REQ_PARAM_CMD = "pipe_cmd";
    static final String CMD_LINE_PREFIX = "cmd_line_";
    static final String WHITE_SPACE_SEPARATOR = "\\s";
    static final String COMMENT_PREFIX = "#";
    static final String SEPARATOR = "|";
    static final String PARAMS = "@";
    static final String KEY_VALUE_SEP = "=";
    static final String FIRST_TOKEN = "first";
    static final String SECOND_TOKEN = "second";
    static final String CONFIGURATION_TOKEN = "(?<" + FIRST_TOKEN + ">[\\w/\\:]+)\\s*" + KEY_VALUE_SEP
        + "(?<" + SECOND_TOKEN + ">[(\\w*)|" + INJECTED_SCRIPT_REGEXP + "]+)";
    static final Pattern CONFIGURATION_PATTERN = Pattern.compile(CONFIGURATION_TOKEN);
    static final String KEY_NAME = "name";
    static final String KEY_PATH = "path";
    static final String KEY_EXPR = "expr";

    private static final String HELP_START =
        "\n a <pipe token> is <pipe> <expr|conf>? (<options>)?" +
        "\n <options> are (@ <option>)* form with <option> being either" +
        "\n\t'name pipeName' (used in bindings), " +
        "\n\t'expr pipeExpression' (when not directly as <args>)" +
        "\n\t'path pipePath' (when not directly as <args>)" +
        "\n\t'with key=value ...'" +
        "\n\t'outputs key=value ...'" +
        "\n and <pipe> is one of the following :\n";

    Map<String, Method> methodMap;
    Map<String, PipeExecutor> executorMap;

    String help;

    @Reference
    Plumber plumber;

    @Activate
    @Modified
    public void activate(){
        methodMap = null;
        executorMap = null;
        help = null;
    }

    boolean isCommandCandidate(String line) {
        return StringUtils.isNotBlank(line) && !line.startsWith(COMMENT_PREFIX);
    }

    List<String> getCommandList(SlingHttpServletRequest request) throws IOException {
        List<String> cmds = new ArrayList<>();
        if (request.getParameterMap().containsKey(REQ_PARAM_CMD)) {
            cmds.add(request.getParameter(REQ_PARAM_CMD));
        } else if (request.getParameterMap().containsKey(REQ_PARAM_FILE)) {
            InputStream is = request.getRequestParameter(REQ_PARAM_FILE).getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
            String line;
            while ((line = reader.readLine()) != null) {
                if (isCommandCandidate(line)) {
                    cmds.add(line);
                }
            }
        }
        return cmds;
    }

    @Override
    protected void doPost(@NotNull SlingHttpServletRequest request, @NotNull SlingHttpServletResponse response) throws ServletException, IOException {
        String currentCommand = null;
        PrintWriter writer = response.getWriter();
        try {
            ResourceResolver resolver = request.getResourceResolver();
            Map<String, Object> bindings = plumber.getBindingsFromRequest(request, true);
            List<String> cmds = getCommandList(request);
            if (cmds.isEmpty()) {
                writer.println("No command to execute!");
            }
            short idx_line = 0;
            for (String command : cmds) {
                if (StringUtils.isNotBlank(command)) {
                    JsonWriter pipeWriter = new JsonWriter();
                    pipeWriter.starts();
                    currentCommand = command;
                    PipeBuilder pipeBuilder = parse(resolver, command.split(WHITE_SPACE_SEPARATOR));
                    Pipe pipe = pipeBuilder.build();
                    bindings.put(CMD_LINE_PREFIX + idx_line++, pipe.getResource().getPath());
                    writer.println(plumber.execute(resolver, pipe, bindings, pipeWriter, true));
                }
            }
            response.setStatus(SC_OK);
        }
        catch (AccessControlException e) {
            response.sendError(SC_FORBIDDEN);
        }
        catch (IllegalAccessException | InvocationTargetException e) {
            writer.println("Error executing " + currentCommand);
            e.printStackTrace(writer);
            response.sendError(SC_INTERNAL_SERVER_ERROR);
            writer.println(help());
        }
    }

    @Override
    public ExecutionResult execute(ResourceResolver resolver, String path, String... optionTokens) {
        Resource resource = resolver.getResource(path);
        if (resource == null){
            throw new IllegalArgumentException(String.format("%s resource does not exist", path));
        }
        Options options = getOptions(optionTokens);
        Map<String, Object> bMap = null;
        if (options.with != null) {
            bMap = new HashMap<>();
            writeToMap(bMap, options.with);
        }
        OutputWriter writer = new NopWriter();
        if (options.writer != null){
            writer = options.writer;
        }
        writer.starts();
        return plumber.execute(resolver, path, bMap, writer, true);
    }

    @Override
    public PipeBuilder parse(ResourceResolver resolver, String...cmds) throws InvocationTargetException, IllegalAccessException {
        PipeBuilder builder = plumber.newPipe(resolver);
        for (Token token : parseTokens(cmds)){
            Method method = getMethodMap().get(token.pipeKey);
            if (method == null){
                throw new IllegalArgumentException(token.pipeKey + " is not a valid pipe");
            }
            if (isExpressionExpected(method)){
                method.invoke(builder, token.args.get(0));
            } else if (isConfExpected(method)){
                method.invoke(builder, (Object)keyValuesToArray(token.args));
            } else if (isWithoutExpectedParameter(method)){
                method.invoke(builder);
            }

            if (token.options != null){
                token.options.writeToBuilder(builder);
            }
        }
        return builder;

    }

    /**
     * ends up processing of current token
     * @param currentToken token being processed
     * @param currentList list of argument that have been collected so far
     */
    protected void finishToken(Token currentToken, List<String> currentList){
        if (currentToken.args != null){
            //it means we have already parse args here, so we need to set current list as options
            currentToken.options = getOptions(currentList);
        } else {
            currentToken.args = currentList;
        }
        log.debug("current token : {}", currentToken);
    }

    /**
     * @param tokens array of tokens
     * @return options from array
     */
    protected Options getOptions(String[] tokens){
        return getOptions(Arrays.asList(tokens));
    }

    /**
     * @param tokens list of tokens
     * @return options from token list
     */
    protected Options getOptions(List<String> tokens){
        return new Options(tokens);
    }

    /**
     * Options for a pipe execution
     */
    protected class Options {
        String name;
        String path;
        String expr;
        String[] with;
        OutputWriter writer;

        @Override
        public String toString() {
            return "Options{" +
                "name='" + name + '\'' +
                ", path='" + path + '\'' +
                ", expr='" + expr + '\'' +
                ", with=" + Arrays.toString(with) +
                ", writer=" + writer +
                '}';
        }

        void setOutputs(List<String> values) {
            this.writer = new JsonWriter();
            String[] list = keyValuesToArray(values);
            Map<String, Object> outputs = new HashMap<>();
            CommandUtil.writeToMap(outputs, list);
            this.writer.setCustomOutputs(outputs);
        }

        /**
         * Constructor
         * @param options string list from where options will be built
         */
        protected Options(List<String> options){
            Map<String, Object> optionMap = new HashMap<>();
            String currentKey = null;
            List<String> currentList = null;


            for (String optionToken : options) {
                if (PARAMS.equals(optionToken)){
                    finishOption(currentKey, currentList, optionMap);
                    currentList = new ArrayList<>();
                    currentKey = null;
                } else if (currentKey == null){
                    currentKey = optionToken;
                } else {
                    currentList.add(optionToken);
                }
            }
            finishOption(currentKey, currentList, optionMap);
            for (Map.Entry<String, Object> entry : optionMap.entrySet()){
                switch (entry.getKey()) {
                    case Pipe.PN_NAME :
                        this.name = (String)entry.getValue();
                        break;
                    case Pipe.PN_PATH :
                        this.path = (String)entry.getValue();
                        break;
                    case Pipe.PN_EXPR :
                        this.expr = (String)entry.getValue();
                        break;
                    case "with" :
                        this.with = keyValuesToArray((List<String>)entry.getValue());
                        break;
                    case "outputs" :
                        setOutputs((List<String>)entry.getValue());
                        break;
                    default:
                        throw new IllegalArgumentException(String.format("%s is an unknown option", entry.getKey()));
                }
            }

        }

        /**
         * wrap up current option
         * @param currentKey option key
         * @param currentList list being processed
         * @param optionMap option map
         */
        protected void finishOption(String currentKey, List<String> currentList, Map<String, Object> optionMap){
            if (currentList != null){
                if (currentKey.equals(KEY_NAME) || currentKey.equals(KEY_EXPR) || currentKey.equals(KEY_PATH)) {
                    optionMap.put(currentKey, currentList.get(0));
                } else {
                    optionMap.put(currentKey, currentList);
                }
            }
        }

        /**
         * write options to current builder
         * @param builder current builder
         * @throws IllegalAccessException
         */
        void writeToBuilder(PipeBuilder builder) throws IllegalAccessException {
            if (StringUtils.isNotBlank(name)){
                builder.name(name);
            }
            if (StringUtils.isNotBlank(path)){
                builder.path(path);
            }
            if (StringUtils.isNotBlank(expr)){
                builder.expr(expr);
            }
            if (with != null){
                builder.with(with);
            }
        }
    }

    /**
     * Pipe token, used to hold information of a "sub pipe" configuration
     */
    protected class Token {
        String pipeKey;
        List<String> args;
        CommandExecutorImpl.Options options;

        @Override
        public String toString() {
            return "Token{" +
                "pipeKey='" + pipeKey + '\'' +
                ", args=" + args +
                ", options=" + options +
                '}';
        }
    }

    /**
     * @param commands full list of command tokens
     * @return Token list corresponding to the string ones
     */
    protected List<CommandExecutorImpl.Token> parseTokens(String... commands) {
        List<CommandExecutorImpl.Token> returnValue = new ArrayList<>();
        CommandExecutorImpl.Token currentToken = new CommandExecutorImpl.Token();
        returnValue.add(currentToken);
        List<String> currentList = new ArrayList<>();
        for (String token : commands){
            if (currentToken.pipeKey == null){
                currentToken.pipeKey = token;
            } else {
                switch (token){
                    case CommandExecutorImpl.SEPARATOR:
                        finishToken(currentToken, currentList);
                        currentList = new ArrayList<>();
                        currentToken = new CommandExecutorImpl.Token();
                        returnValue.add(currentToken);
                        break;
                    case CommandExecutorImpl.PARAMS:
                        if (currentToken.args == null){
                            currentToken.args = currentList;
                            currentList = new ArrayList<>();
                        }
                        currentList.add(PARAMS);
                        break;
                    default:
                        currentList.add(token);
                }
            }
        }
        finishToken(currentToken, currentList);
        return returnValue;
    }

    /**
     * builds utility maps
     */
    protected void computeMaps(){
        executorMap = new HashMap<>();
        methodMap = new HashMap<>();
        for (Method method : PipeBuilder.class.getDeclaredMethods()) {
            PipeExecutor executor = method.getAnnotation(PipeExecutor.class);
            if (executor != null) {
                methodMap.put(executor.command(), method);
                executorMap.put(executor.command(), executor);
            }
        }
    }

    /**
     * @return map of command to PB api method
     */
    protected Map<String, Method> getMethodMap() {
        if (methodMap == null) {
            computeMaps();
        }
        return methodMap;
    }

    /**
     * @return map of command to Annotation information around the PB api
     */
    protected Map<String, PipeExecutor> getExecutorMap() {
        if (executorMap == null) {
            computeMaps();
        }
        return executorMap;
    }

    /**
     * @param method corresponding PB api
     * @return true if the api does expect an expression (meaning a string)
     */
    protected boolean isExpressionExpected(Method method) {
        return method.getParameterCount() == 1 && method.getParameterTypes()[0].equals(String.class);
    }

    /**
     * @param method corresponding PB api
     * @return true if the api does expect a configuration (meaning a list of key value pairs)
     */
    protected boolean isConfExpected(Method method) {
        return method.getParameterCount() == 1 && method.getParameterTypes()[0].equals(Object[].class);
    }

    /**
     * @param method corresponding PB api
     * @return true if the api does not expect parameters
     */
    protected boolean isWithoutExpectedParameter(Method method){
        return method.getParameterCount() == 0;
    }

    /**
     * @param o list of key value strings key1=value1,key2=value2,...
     * @return String [] key1,value1,key2,value2,... corresponding to the pipe builder API
     */
    String[] keyValuesToArray(List<String> o) {
        List<String> args = new ArrayList<>();
        for (String pair : o){
            Matcher matcher = CONFIGURATION_PATTERN.matcher(pair.trim());
            if (matcher.matches()) {
                args.add(matcher.group(FIRST_TOKEN));
                args.add(matcher.group(SECOND_TOKEN));
            }
        }
        return args.toArray(new String[args.size()]);
    }

    /**
     * help command handler
     */
    public String help(){
        if (StringUtils.isBlank(help)) {
            StringBuilder builder = new StringBuilder();
            builder.append(HELP_START);
            for (Map.Entry<String, PipeExecutor> entry : getExecutorMap().entrySet()) {
                builder.append(String.format("\t%s\t\t:\t%s%n", entry.getKey(), entry.getValue().description()));
            }
            help = builder.toString();
        }
        return help;
    }

}
