/*
 * 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.util;

import com.intellij.execution.process.UnixProcessManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.AtomicNotNullLazyValue;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.concurrency.FixedFuture;
import com.intellij.util.text.CaseInsensitiveStringHashingStrategy;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class EnvironmentUtil {
  private static final Logger LOG = Logger.getInstance("#com.intellij.util.EnvironmentUtil");

  private static final int SHELL_ENV_READING_TIMEOUT = 10000;

  private static final Future<Map<String, String>> ourEnvGetter;
  static {
    if (SystemInfo.isMac && Registry.is("idea.fix.mac.env")) {
      ExecutorService executor = Executors.newSingleThreadExecutor();
      ourEnvGetter = executor.submit(new Callable<Map<String, String>>() {
        @Override
        public Map<String, String> call() throws Exception {
          try {
            return getShellEnv();
          }
          catch (Throwable t) {
            LOG.warn("can't get shell environment", t);
            return System.getenv();
          }
        }
      });
      executor.shutdown();
    }
    else {
      ourEnvGetter = new FixedFuture<Map<String, String>>(System.getenv());
    }
  }

  private static final NotNullLazyValue<Map<String, String>> ourEnvironment = new AtomicNotNullLazyValue<Map<String, String>>() {
    @NotNull
    @Override
    protected Map<String, String> compute() {
      try {
        return ourEnvGetter.get();
      }
      catch (Exception e) {
        LOG.warn(e);
        return System.getenv();
      }
    }
  };

  private static final NotNullLazyValue<Map<String, String>> ourEnvironmentOsSpecific = new AtomicNotNullLazyValue<Map<String, String>>() {
    @NotNull
    @Override
    protected Map<String, String> compute() {
      Map<String, String> env = ourEnvironment.getValue();
      if (SystemInfo.isWindows) {
        env = Collections.unmodifiableMap(new THashMap<String, String>(env, CaseInsensitiveStringHashingStrategy.INSTANCE));
      }
      return env;
    }
  };

  private EnvironmentUtil() { }

  public static boolean isEnvironmentReady() {
    return ourEnvGetter.isDone();
  }

  /**
   * Returns the process environment.
   * On Mac OS X a shell (Terminal.app) environment is returned (unless disabled by a system property).
   *
   * @return unmodifiable map of the process environment.
   */
  @NotNull
  public static Map<String, String> getEnvironmentMap() {
    return ourEnvironment.getValue();
  }

  /**
   * Returns value for the passed environment variable name.
   * The passed environment variable name is handled in a case-sensitive or case-insensitive manner depending on OS.<p>
   * For example, on Windows <code>getValue("Path")</code> will return the same result as <code>getValue("PATH")</code>.
   *
   * @param name environment variable name
   * @return value of the environment variable or null if no such variable found
   */
  @Nullable
  public static String getValue(@NotNull String name) {
    return ourEnvironmentOsSpecific.getValue().get(name);
  }

  public static String[] getEnvironment() {
    return flattenEnvironment(getEnvironmentMap());
  }

  public static String[] flattenEnvironment(Map<String, String> environment) {
    String[] array = new String[environment.size()];
    int i = 0;
    for (Map.Entry<String, String> entry : environment.entrySet()) {
      array[i++] = entry.getKey() + "=" + entry.getValue();
    }
    return array;
  }

  private static Map<String, String> getShellEnv() throws Exception {
    String shell = System.getenv("SHELL");
    if (shell == null || !new File(shell).canExecute()) {
      throw new Exception("shell:" + shell);
    }

    File reader = FileUtil.findFirstThatExist(
      PathManager.getBinPath() + "/printenv.py",
      PathManager.getHomePath() + "/community/bin/mac/printenv.py",
      PathManager.getHomePath() + "/bin/mac/printenv.py"
    );
    if (reader == null) {
      throw new Exception("bin:" + PathManager.getBinPath());
    }

    File envFile = FileUtil.createTempFile("intellij-shell-env", null, false);
    try {
      String[] command = {shell, "-l", "-c", "'" + reader.getAbsolutePath() + "' '" + envFile.getAbsolutePath() + "'"};
      LOG.info("loading shell env: " + StringUtil.join(command, " "));

      Process process = Runtime.getRuntime().exec(command);
      ProcessKiller processKiller = new ProcessKiller(process);
      processKiller.killAfter(SHELL_ENV_READING_TIMEOUT);
      int rv = process.waitFor();
      processKiller.stopWaiting();

      String lines = FileUtil.loadFile(envFile);
      if (rv != 0 || lines.isEmpty()) {
        throw new Exception("rv:" + rv + " text:" + lines.length());
      }
      return parseEnv(lines);
    }
    finally {
      FileUtil.delete(envFile);
    }
  }

  private static Map<String, String> parseEnv(String text) throws Exception {
    Set<String> toIgnore = new HashSet<String>(Arrays.asList("_", "PWD", "SHLVL"));
    Map<String, String> env = System.getenv();
    Map<String, String> newEnv = new HashMap<String, String>();

    String[] lines = text.split("\0");
    for (String line : lines) {
      int pos = line.indexOf('=');
      if (pos <= 0) {
        throw new Exception("malformed:" + line);
      }
      String name = line.substring(0, pos);
      if (!toIgnore.contains(name)) {
        newEnv.put(name, line.substring(pos + 1));
      }
      else if (env.containsKey(name)) {
        newEnv.put(name, env.get(name));
      }
    }

    LOG.info("shell environment loaded (" + newEnv.size() + " vars)");
    return Collections.unmodifiableMap(newEnv);
  }

  public static String getProcessList() {
    String diagnostics;
    try {
      Process p = Runtime.getRuntime().exec(SystemInfo.isWindows ? System.getenv("windir") +"\\system32\\tasklist.exe /v" : "ps a");
      diagnostics = StreamUtil.readText(p.getInputStream());
    }
    catch (IOException e) {
      diagnostics = ExceptionUtil.getThrowableText(e);
    }
    return diagnostics;
  }

  private static class ProcessKiller {
    private final Process myProcess;
    private final Object myWaiter = new Object();

    public ProcessKiller(Process process) {
      myProcess = process;
    }

    public void killAfter(long timeout) {
      final long stop = System.currentTimeMillis() + timeout;
      new Thread() {
        @Override
        public void run() {
          synchronized (myWaiter) {
            while (System.currentTimeMillis() < stop) {
              try {
                myProcess.exitValue();
                break;
              }
              catch (IllegalThreadStateException ignore) { }

              try {
                myWaiter.wait(100);
              }
              catch (InterruptedException ignore) { }
            }
          }

          try {
            myProcess.exitValue();
          }
          catch (IllegalThreadStateException e) {
            UnixProcessManager.sendSigIntToProcessTree(myProcess);
            LOG.warn("timed out");
          }
        }
      }.start();
    }

    public void stopWaiting() {
      synchronized (myWaiter) {
        myWaiter.notifyAll();
      }
    }
  }

  /** @deprecated use {@link #getEnvironmentMap()} (to remove in IDEA 14) */
  @SuppressWarnings({"UnusedDeclaration", "SpellCheckingInspection"})
  public static Map<String, String> getEnviromentProperties() {
    return getEnvironmentMap();
  }

  /** @deprecated use {@link #getEnvironmentMap()} (to remove in IDEA 14) */
  @SuppressWarnings({"UnusedDeclaration", "SpellCheckingInspection"})
  public static Map<String, String> getEnvironmentProperties() {
    return getEnvironmentMap();
  }

  @TestOnly
  static Map<String, String> testLoader() {
    try {
      return getShellEnv();
    }
    catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  @TestOnly
  static Map<String, String> testParser(@NotNull String lines) {
    try {
      return parseEnv(lines);
    }
    catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
}
