/*
 * 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 org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.pipes.AbstractPipeTest;
import org.apache.sling.pipes.ExecutionResult;
import org.apache.sling.pipes.PipeBuilder;
import org.apache.sling.testing.mock.sling.ResourceResolverType;
import org.apache.sling.testing.mock.sling.junit.SlingContext;
import org.apache.sling.testing.mock.sling.servlet.MockRequestPathInfo;
import org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletRequest;
import org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletResponse;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.apache.sling.pipes.internal.CommandExecutorImpl.PARAMS_SEPARATOR;
import static org.apache.sling.pipes.internal.CommandUtil.keyValuesToArray;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonString;
import javax.servlet.ServletException;

public class CommandExecutorImplTest extends AbstractPipeTest {

    CommandExecutorImpl commands;

    @Before
    public void setup() throws PersistenceException {
        super.setup();
        context = new SlingContext(ResourceResolverType.JCR_OAK);
        context.load().json("/initial-content/content/fruits.json", PATH_FRUITS);
        commands = new CommandExecutorImpl();
        commands.plumber = plumber;
    }

    @Test
    public void getSublist() {
        assertArrayEquals(new String[]{"check", "this"}, commands.getSpaceSeparatedTokens("check this").toArray());
        assertArrayEquals(new String[]{"and", "now","check this"}, commands.getSpaceSeparatedTokens("and now \"check this\"").toArray());
    }

        @Test
    public void testParseTokens() {
        List<CommandExecutorImpl.Token> tokens = commands.parseTokens("some isolated items");
        assertEquals("there should be 1 token", 1, tokens.size());
        CommandExecutorImpl.Token token = tokens.get(0);
        assertEquals("pipe key should be 'some'", "some", token.pipeKey);
        assertEquals("pipe args should be isolated, items", Arrays.asList("isolated", "items"), token.args);
    }
    @Test
    public void testParseTokensWithQuotes() {
        String tokenString = "first arg | second firstarg secondarg @ name second | third blah";
        List<CommandExecutorImpl.Token> tokens = commands.parseTokens(tokenString);
        assertEquals("there should be 3 tokens", 3, tokens.size());
        assertEquals("keys check", Arrays.asList("first","second", "third"), tokens.stream().map(t -> t.pipeKey).collect(Collectors.toList()));
        assertEquals("params check", "second", tokens.get(1).options.name);
    }

    @Test
    public void testParseJson() {
        String tokenString = "json [{\"title\":\"this is the first\", \"path\":\"/content/nested/two\"}, {\"title\":\"this is the second\", \"path\":\"/content/nested/three\"}]";
        List<CommandExecutorImpl.Token> tokens = commands.parseTokens(tokenString);
        assertEquals("there should be 1 token", 1, tokens.size());
        assertEquals("there should be 1 arg", 1, tokens.get(0).args.size());
    }

    @Test
    public void testQuotedTokens() {
        List<CommandExecutorImpl.Token> tokens = commands.parseTokens("some isolated items \"with quotes\"");
        assertEquals("there should be 1 token", 1, tokens.size());
        CommandExecutorImpl.Token token = tokens.get(0);
        assertEquals("pipe args should be isolated, items", Arrays.asList("isolated", "items", "with quotes"), token.args);
    }

    @Test
    public void testKeyValueToArray() {
        assertArrayEquals("1", new String[]{"one","two","three","four"}, keyValuesToArray(Arrays.asList("one=two","three=four")));
        assertArrayEquals("2", new String[]{"one","two","three","${four}"}, keyValuesToArray(Arrays.asList("one=two","three=${four}")));
        assertArrayEquals("3", new String[]{"${one == 'check'? 'three':'four'}","two"}, keyValuesToArray((Arrays.asList("${one == 'check'? 'three':'four'}=two"))));
        assertArrayEquals("4", new String[]{"a_b-c","two"}, keyValuesToArray((Arrays.asList("a_b-c=two"))));
        assertArrayEquals("5", new String[]{"one","two","three","${four == 'blah' ? 'five' : 'six'}"},
            keyValuesToArray(Arrays.asList("one=two","three=${four == 'blah' ? 'five' : 'six'}")));
        assertArrayEquals("6", new String[]{"jcr:content/singer","${'ringo' == one ? false : true}"}, keyValuesToArray(Arrays.asList("jcr:content/singer=${'ringo' == one ? false : true}")));
    }

    @Test
    public void testSimpleExpression() throws Exception {
        PipeBuilder builder = commands.parse(context.resourceResolver(),"echo /content/fruits");
        assertTrue("there should be a resource", builder.build().getOutput().hasNext());
    }

    @Test
    public void testSimpleChainedConf() throws Exception {
        PipeBuilder builder = commands.parse(context.resourceResolver(),"echo /content/fruits | write some=test key=value");
        assertNotNull("there should be a resource", builder.run());
        ValueMap props = context.currentResource(PATH_FRUITS).getValueMap();
        assertEquals("there should some=test", "test", props.get("some"));
        assertEquals("there should key=value", "value", props.get("key"));
    }

    @Test
    public void testOptions() {
        String expected = "works";
        String optionString = "name works @ path works @ expr works @ with one=works two=works @ outputs one=works two=works";
        CommandExecutorImpl.Options options = commands.getOptions(optionString.split(PARAMS_SEPARATOR));
        assertEquals("check name", expected, options.name);
        assertEquals("check expr", expected, options.expr);
        assertEquals("check path", expected, options.path);
        Map bindings = new HashMap();
        CommandUtil.writeToMap(bindings, true, options.with);
        assertEquals("check with first", expected, bindings.get("one"));
        assertEquals("check with second", expected, bindings.get("two"));
        assertNotNull("a writer should have been created", options.outputs);
    }

    @Test
    public void testOptionsListsWithOneItem() {
        String expected = "works";
        String optionString = "with one=works @ outputs one=works";
        CommandExecutorImpl.Options options = commands.getOptions(optionString.split(PARAMS_SEPARATOR));
        Map bindings = new HashMap();
        CommandUtil.writeToMap(bindings, true, options.with);
        assertEquals("check with first", expected, bindings.get("one"));
        assertNotNull("a writer should have been created", options.outputs);
    }

    @Test
    public void testChainedConfWithInternalOptions() throws Exception {
        PipeBuilder builder = commands.parse(context.resourceResolver(),
        "echo /content/fruits @ name fruits | write some=${path.fruits} key=value");
        assertNotNull("there should be a resource", builder.run());
        ValueMap props = context.currentResource(PATH_FRUITS).getValueMap();
        assertEquals("there should some=/content/fruits", PATH_FRUITS, props.get("some"));
        assertEquals("there should key=value", "value", props.get("key"));
    }

    @Test
    public void testNonBreakingSpaces() throws InvocationTargetException, IllegalAccessException {
        ExecutionResult result = execute("echo /content | mkdir test @ name child");
        assertEquals(1, result.size());
    }

    @Test
    public void adaptToDemoTest() throws Exception {
        String url = "'http://99-bottles-of-beer.net/lyrics.html'";
        String cmd = "egrep " + url + " @ name bottles @ with pattern=(?<number>\\d(\\d)?) | mkdir /var/bottles/${bottles.number}";
        PipeBuilder builder = commands.parse(context.resourceResolver(), cmd);
        ContainerPipe pipe = (ContainerPipe)builder.build();
        ValueMap regexp = pipe.getResource().getChild("conf/bottles").getValueMap();
        assertEquals("we expect expr to be the url", url, regexp.get("expr"));
    }

    @Test
    public void testExecuteWithWriter() throws Exception {
        PipeBuilder builder = plumber.newPipe(context.resourceResolver()).echo("/content/${node}").$("nt:base");
        String path = builder.build().getResource().getPath();
        ExecutionResult result = commands.execute(context.resourceResolver(), path, "outputs title=two['jcr:title'] desc=two['jcr:description']", "with node=fruits");
        assertNotNull(result);
    }

    String testRawServlet(Map<String,Object> params) throws IOException {
        MockSlingHttpServletRequest request = context.request();
        MockSlingHttpServletResponse response = context.response();
        request.setParameterMap(params);
        MockRequestPathInfo pathInfo = (MockRequestPathInfo)request.getRequestPathInfo();
        pathInfo.setExtension("json");
        request.setMethod("POST");
        commands.doPost(request, response);
        if (response.getStatus() != 200) {
            System.out.println(response.getOutputAsString());
        }
        assertEquals(200, response.getStatus());
        return response.getOutputAsString();
    }
    JsonObject testServlet(Map<String,Object> params) throws ServletException, IOException {
        return (JsonObject) JsonUtil.parse(testRawServlet(params));
    }

    @Test
    public void testHelp() throws ServletException, IOException {
        Map<String, Object> params = new HashMap<>();
        params.put(CommandExecutorImpl.REQ_PARAM_HELP, "blah");
        String response = testRawServlet(params);
        assertTrue(StringUtils.isNotBlank(response));
    }

    @Test
    public void testSimpleCommandServlet() throws IOException, ServletException {
        Map<String, Object> params = new HashMap<>();
        params.put(CommandExecutorImpl.REQ_PARAM_CMD, "echo /content | mkdir foo | write type=bar");
        JsonObject response = testServlet(params);
        assertEquals(1, response.getJsonNumber("size").intValue());
        assertEquals("/content/foo", response.getJsonArray("items").getString(0));
    }

    @Test
    public void testMultipeLineGetCommandLine() throws IOException, ServletException {
        Map<String, Object> params = new HashMap<>();
        params.put(CommandExecutorImpl.REQ_PARAM_FILE, IOUtils.toString(getClass().getResourceAsStream("/commandsFormats"
            + ".txt"), "UTF-8"));
        MockSlingHttpServletRequest request = context.request();
        request.setParameterMap(params);
        request.setMethod("POST");
        List<String> cmdList = commands.getCommandList(context.request());
        assertEquals(5, cmdList.size());
        for (int i = 0; i < 3; i ++) {
            assertEquals("echo /content | $ /apps/pipes-it/fruit | children nt:unstructured", cmdList.get(i));
        }
        assertEquals ("echo /content | write one=foo nested/two=foo nested/three=foo", cmdList.get(3));
        assertEquals("echo /content | json [{\"title\":\"this is the first\", \"path\":\"/content/nested/two\"}, {\"title\":\"this is the second\", \"path\":\"/content/nested/three\"}] @ name test | echo ${test.path}", cmdList.get(4));
    }

    String[] getItemsArray(JsonObject response) {
        JsonArray jsonItems = response.getJsonArray("items");
        List<String> items = jsonItems.stream().map(o -> ((JsonString)o).getString()).collect(Collectors.toList());
        return items.toArray(new String[jsonItems.size()]);
    }

    @Test
    public void testChainedCommand() throws IOException, ServletException {
        Map<String, Object> params = new HashMap<>();
        params.put(CommandExecutorImpl.REQ_PARAM_FILE, IOUtils.toString(getClass().getResourceAsStream("/chainedCommand"
            + ".txt"), "UTF-8"));
        JsonObject response = testServlet(params);
        assertEquals(5, response.getJsonNumber("size").intValue());
        assertArrayEquals(new String[]{ "/content/fruits/banana/isnota/pea","/content/fruits/banana/isnota/carrot",
            "/content/fruits/apple/isnota/pea","/content/fruits/apple/isnota/plum",
            "/content/fruits/apple/isnota/carrot"}, getItemsArray(response));
    }

    @Test
    public void testFileCommandServlet() throws IOException, ServletException {
        Map<String, Object> params = new HashMap<>();
        params.put(CommandExecutorImpl.REQ_PARAM_FILE, IOUtils.toString(getClass().getResourceAsStream("/testcommand"
                + ".txt"), "UTF-8"));
        JsonObject response = testServlet(params);
        assertEquals(5, response.getJsonNumber("size").intValue());
        assertArrayEquals(new String[]{"/content/beatles/john", "/content/beatles/paul", "/content/beatles/georges",
                "/content/beatles/ringo", "/content/beatles/ringo/jcr:content"}, getItemsArray(response));
    }
}