/*
 * Copyright 2000-2013 JetBrains s.r.o.
 *
 * Licensed 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 com.intellij.execution;

import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.util.ExecUtil;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
import org.jetbrains.annotations.Nullable;
import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.*;

import static org.junit.Assert.*;
import static org.junit.Assume.assumeTrue;

public class GeneralCommandLineTest {
  @Test
  public void printCommandLine() {
    GeneralCommandLine commandLine = new GeneralCommandLine();
    commandLine.setExePath("e x e path");
    commandLine.addParameter("with space");
    commandLine.addParameter("\"quoted\"");
    commandLine.addParameter("\"quoted with spaces\"");
    commandLine.addParameters("param 1", "param2");
    commandLine.addParameter("trailing slash\\");
    assertEquals("\"e x e path\"" +
                 " \"with space\"" +
                 " \\\"quoted\\\"" +
                 " \"\\\"quoted with spaces\\\"\"" +
                 " \"param 1\"" +
                 " param2" +
                 " \"trailing slash\\\"",
                 commandLine.getCommandLineString());
  }

  @Test
  public void unicodePath() throws Exception {
    String mark = String.valueOf(new Random().nextInt());
    File script;
    if (SystemInfo.isWindows) {
      script = ExecUtil.createTempExecutableScript(
        "path with spaces 'and quotes' и юникодом ", ".cmd",
        "@echo " + mark + "\n"
      );
    }
    else {
      script = ExecUtil.createTempExecutableScript(
        "path with spaces 'and quotes' и юникодом ", ".sh",
        "#!/bin/sh\n" + "echo " + mark + "\n"
      );
    }

    try {
      GeneralCommandLine commandLine = new GeneralCommandLine(script.getPath());
      String output = execAndGetOutput(commandLine, null);
      assertEquals(mark + "\n", StringUtil.convertLineSeparators(output));
    }
    finally {
      FileUtil.delete(script);
    }
  }

  @Test
  public void unicodeClassPath() throws Exception {
    assumeTrue(SystemInfo.isUnix);

    File dir = FileUtil.createTempDirectory("path with spaces 'and quotes' и юникодом ", ".tmp");
    try {
      GeneralCommandLine commandLine = makeJavaCommand(ParamPassingTest.class, dir);
      String output = execAndGetOutput(commandLine, null);
      assertEquals("=====\n=====\n", StringUtil.convertLineSeparators(output));
    }
    finally {
      FileUtil.delete(dir);
    }
  }

  @Test
  public void argumentsPassing() throws Exception {
    String[] parameters = {
      "with space", "\"quoted\"", "\"quoted with spaces\"", "", "  ", "param 1", "\"", "param2", "trailing slash\\"
    };

    GeneralCommandLine commandLine = makeJavaCommand(ParamPassingTest.class, null);
    commandLine.addParameters(parameters);
    String output = execAndGetOutput(commandLine, null);
    assertEquals("=====\n" + StringUtil.join(parameters, new Function<String, String>() {
      @Override
      public String fun(String s) {
        return ParamPassingTest.format(s);
      }
    }, "\n") + "\n=====\n", StringUtil.convertLineSeparators(output));
  }

  @Test
  public void unicodeArguments() throws Exception {
    assumeTrue("UTF-8".equals(System.getProperty("file.encoding")));

    File script;
    GeneralCommandLine commandLine;
    String encoding = null;
    if (SystemInfo.isWindows) {
      script = ExecUtil.createTempExecutableScript(
        "args.", ".js",
        "WSH.Echo(\"=====\");\n" +
        "for (i = 0; i < WSH.Arguments.length; i++) {\n" +
        "  WSH.Echo(WSH.Arguments(i));\n" +
        "}\n" +
        "WSH.Echo(\"=====\");\n"
      );
      commandLine = new GeneralCommandLine("cscript", "//Nologo", "//U", script.getPath());
      encoding = "UTF-16LE";
    }
    else {
      script = ExecUtil.createTempExecutableScript(
        "args.", ".sh",
        "#!/bin/sh\n\n" +
        "echo \"=====\"\n" +
        "for f in \"$@\" ; do echo \"$f\"; done\n" +
        "echo \"=====\"\n"
      );
      commandLine = new GeneralCommandLine(script.getPath());
    }

    try {
      commandLine.addParameters("немного", "юникодных", "параметров");
      String output = execAndGetOutput(commandLine, encoding);
      assertEquals("=====\nнемного\nюникодных\nпараметров\n=====\n", StringUtil.convertLineSeparators(output));
    }
    finally {
      FileUtil.delete(script);
    }
  }

  @Test
  public void winShellCommand() throws Exception {
    assumeTrue(SystemInfo.isWindows);

    String string = "http://localhost/wtf?a=b&c=d";
    String echo = ExecUtil.execAndReadLine(ExecUtil.getWindowsShellName(), "/c", "echo", string);
    assertEquals('"' + string + '"', echo);
  }

  @Test
  public void winShellScriptQuoting() throws Exception {
    assumeTrue(SystemInfo.isWindows);
    String scriptPrefix = "my_script";
    for (String cmdScriptExt : new String[] {".cmd", ".bat"}) {
      File script = ExecUtil.createTempExecutableScript(
        scriptPrefix, cmdScriptExt,
        "@echo %1\n"
      );
      String param = "a&b";
      GeneralCommandLine commandLine = new GeneralCommandLine(script.getAbsolutePath(), param);
      String text = commandLine.getPreparedCommandLine(Platform.WINDOWS);
      assertEquals(commandLine.getExePath() + "\n" + StringUtil.wrapWithDoubleQuote(param), text);
      try {
        String output = execAndGetOutput(commandLine, null);
        assertEquals(StringUtil.wrapWithDoubleQuote(param), output.trim());
      }
      finally {
        FileUtil.delete(script);
      }
    }
  }

  @Test
  public void winShellQuotingWithExtraSwitch() throws Exception {
    assumeTrue(SystemInfo.isWindows);
    String param = "a&b";
    GeneralCommandLine commandLine = new GeneralCommandLine("cmd", "/D", "/C", "echo", param);
    String output = execAndGetOutput(commandLine, null);
    assertEquals(StringUtil.wrapWithDoubleQuote(param), output.trim());
  }

  @Test
  public void hackyEnvMap () throws Exception {
    GeneralCommandLine commandLine = new GeneralCommandLine();
    //noinspection ConstantConditions
    commandLine.getEnvironment().putAll(null);
  }

  @Test
  public void environmentPassing() throws Exception {
    Map<String, String> testEnv = new HashMap<String, String>();
    testEnv.put("VALUE_1", "some value");
    testEnv.put("VALUE_2", "another\n\"value\"");

    GeneralCommandLine commandLine = makeJavaCommand(EnvPassingTest.class, null);
    checkEnvPassing(commandLine, testEnv, true);
    checkEnvPassing(commandLine, testEnv, false);
  }

  @Test
  public void unicodeEnvironment() throws Exception {
    assumeTrue("UTF-8".equals(System.getProperty("file.encoding")));

    Map<String, String> testEnv = new HashMap<String, String>();
    testEnv.put("VALUE_1", "немного");
    testEnv.put("VALUE_2", "юникода");

    GeneralCommandLine commandLine = makeJavaCommand(EnvPassingTest.class, null);
    checkEnvPassing(commandLine, testEnv, true);
    checkEnvPassing(commandLine, testEnv, false);
  }


  private static String execAndGetOutput(GeneralCommandLine commandLine, @Nullable String encoding) throws Exception {
    Process process = commandLine.createProcess();
    byte[] bytes = FileUtil.loadBytes(process.getInputStream());
    String output = encoding != null ? new String(bytes, encoding) : new String(bytes);
    int result = process.waitFor();
    assertEquals("Command:\n" + commandLine.getCommandLineString() + "\nOutput:\n" + output, 0, result);
    return output;
  }

  private GeneralCommandLine makeJavaCommand(Class<?> testClass, @Nullable File copyTo) throws IOException {
    String className = testClass.getName();
    URL url = getClass().getClassLoader().getResource(className.replace(".", "/") + ".class");
    assertNotNull(url);

    GeneralCommandLine commandLine = new GeneralCommandLine();
    commandLine.setExePath(System.getProperty("java.home") + (SystemInfo.isWindows ? "\\bin\\java.exe" : "/bin/java"));

    String encoding = System.getProperty("file.encoding");
    if (encoding != null) {
      commandLine.addParameter("-D" + "file.encoding=" + encoding);
    }

    commandLine.addParameter("-cp");
    String[] packages = className.split("\\.");
    File classFile = new File(url.getFile());
    if (copyTo == null) {
      File dir = classFile;
      for (String ignored : packages) dir = dir.getParentFile();
      commandLine.addParameter(dir.getPath());
    }
    else {
      File dir = copyTo;
      for (int i = 0; i < packages.length - 1; i++) dir = new File(dir, packages[i]);
      FileUtil.copy(classFile, new File(dir, classFile.getName()));
      commandLine.addParameter(copyTo.getPath());
    }

    commandLine.addParameter(className);
    commandLine.setRedirectErrorStream(true);

    return commandLine;
  }

  private static void checkEnvPassing(GeneralCommandLine commandLine, Map<String, String> testEnv, boolean passParentEnv) throws Exception {
    commandLine.getEnvironment().putAll(testEnv);
    commandLine.setPassParentEnvironment(passParentEnv);
    String output = execAndGetOutput(commandLine, null);

    Set<String> lines = new HashSet<String>(Arrays.asList(StringUtil.convertLineSeparators(output).split("\n")));
    lines.remove("=====");

    for (Map.Entry<String, String> entry : testEnv.entrySet()) {
      String str = EnvPassingTest.format(entry);
      assertTrue("\"" + str + "\" should be in " + lines,
                 lines.contains(str));
    }

    Map<String, String> parentEnv = System.getenv();
    List<String> missed = new ArrayList<String>();
    for (Map.Entry<String, String> entry : parentEnv.entrySet()) {
      String str = EnvPassingTest.format(entry);
      if (!lines.contains(str)) {
        missed.add(str);
      }
    }

    long pctMissed = Math.round((100.0 * missed.size()) / parentEnv.size());
    if (passParentEnv && pctMissed > 25 || !passParentEnv && pctMissed < 75) {
      fail("% missed: " + pctMissed + ", missed: " + missed + ", passed: " + lines);
    }
  }
}
