/*
 * Copyright 2000-2014 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.openapi.projectRoots.impl;

import com.intellij.execution.util.ExecUtil;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.projectRoots.*;
import com.intellij.openapi.roots.AnnotationOrderRootType;
import com.intellij.openapi.roots.JavadocOrderRootType;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.*;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.impl.JavaSdkUtil;

import javax.swing.*;
import java.io.File;
import java.io.FileFilter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Eugene Zhuravlev
 * @since Sep 17, 2004
 */
public class JavaSdkImpl extends JavaSdk {
  private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.projectRoots.impl.JavaSdkImpl");
  // do not use javaw.exe for Windows because of issues with encoding
  @NonNls private static final String VM_EXE_NAME = "java";
  @NonNls private final Pattern myVersionStringPattern = Pattern.compile("^(.*)java version \"([1234567890_.]*)\"(.*)$");
  @NonNls private static final String JAVA_VERSION_PREFIX = "java version ";
  @NonNls private static final String OPENJDK_VERSION_PREFIX = "openjdk version ";
  public static final DataKey<Boolean> KEY = DataKey.create("JavaSdk");

  public JavaSdkImpl() {
    super("JavaSDK");
  }

  @Override
  public String getPresentableName() {
    return ProjectBundle.message("sdk.java.name");
  }

  @Override
  public Icon getIcon() {
    return AllIcons.Nodes.PpJdk;
  }

  @NotNull
  @Override
  public String getHelpTopic() {
    return "reference.project.structure.sdk.java";
  }

  @Override
  public Icon getIconForAddAction() {
    return AllIcons.General.AddJdk;
  }

  @NonNls
  @Override
  @Nullable
  public String getDefaultDocumentationUrl(@NotNull final Sdk sdk) {
    final JavaSdkVersion version = getVersion(sdk);
    if (version == JavaSdkVersion.JDK_1_5) {
      return "http://docs.oracle.com/javase/1.5.0/docs/api/";
    }
    if (version == JavaSdkVersion.JDK_1_6) {
      return "http://docs.oracle.com/javase/6/docs/api/";
    }
    if (version == JavaSdkVersion.JDK_1_7) {
      return "http://docs.oracle.com/javase/7/docs/api/";
    }
    if (version == JavaSdkVersion.JDK_1_8) {
      return "http://docs.oracle.com/javase/8/docs/api";
    }
    return null;
  }

  @Override
  public AdditionalDataConfigurable createAdditionalDataConfigurable(SdkModel sdkModel, SdkModificator sdkModificator) {
    return null;
  }

  @Override
  public void saveAdditionalData(@NotNull SdkAdditionalData additionalData, @NotNull Element additional) {
  }

  @Override
  @SuppressWarnings({"HardCodedStringLiteral"})
  public String getBinPath(@NotNull Sdk sdk) {
    return getConvertedHomePath(sdk) + "bin";
  }

  @Override
  @NonNls
  public String getToolsPath(@NotNull Sdk sdk) {
    final String versionString = sdk.getVersionString();
    final boolean isJdk1_x = versionString != null && (versionString.contains("1.0") || versionString.contains("1.1"));
    return getConvertedHomePath(sdk) + "lib" + File.separator + (isJdk1_x? "classes.zip" : "tools.jar");
  }

  @Override
  public String getVMExecutablePath(@NotNull Sdk sdk) {
    /*
    if ("64".equals(System.getProperty("sun.arch.data.model"))) {
      return getBinPath(sdk) + File.separator + System.getProperty("os.arch") + File.separator + VM_EXE_NAME;
    }
    */
    return getBinPath(sdk) + File.separator + VM_EXE_NAME;
  }

  private static String getConvertedHomePath(Sdk sdk) {
    String homePath = sdk.getHomePath();
    assert homePath != null : sdk;
    String path = FileUtil.toSystemDependentName(homePath);
    if (!path.endsWith(File.separator)) {
      path += File.separator;
    }
    return path;
  }

  @Override
  @SuppressWarnings({"HardCodedStringLiteral"})
  public String suggestHomePath() {
    if (SystemInfo.isMac) {
      if (new File("/usr/libexec/java_home").exists()) {
        final String path = ExecUtil.execAndReadLine("/usr/libexec/java_home");
        if (path != null && new File(path).exists()) {
          return path;
        }
      }
      return "/System/Library/Frameworks/JavaVM.framework/Versions";
    }

    if (SystemInfo.isLinux) {
      final String[] homes = {"/usr/java", "/opt/java", "/usr/lib/jvm"};
      for (String home : homes) {
        if (new File(home).isDirectory()) {
          return home;
        }
      }
    }

    if (SystemInfo.isSolaris) {
      return "/usr/jdk";
    }

    if (SystemInfo.isWindows) {
      String property = System.getProperty("java.home");
      if (property == null) return null;
      File javaHome = new File(property).getParentFile();//actually java.home points to to jre home
      if (javaHome != null && JdkUtil.checkForJdk(javaHome)) {
        return javaHome.getAbsolutePath();
      }
    }
    return null;
  }

  @NotNull
  @Override
  public Collection<String> suggestHomePaths() {
    if (!SystemInfo.isWindows)
      return Collections.singletonList(suggestHomePath());

    String property = System.getProperty("java.home");
    if (property == null)
      return Collections.emptyList();

    File javaHome = new File(property).getParentFile();//actually java.home points to to jre home
    if (javaHome == null || !javaHome.isDirectory() || javaHome.getParentFile() == null) {
      return Collections.emptyList();
    }
    ArrayList<String> result = new ArrayList<String>();
    File javasFolder = javaHome.getParentFile();
    scanFolder(javasFolder, result);
    File parentFile = javasFolder.getParentFile();
    File root = parentFile != null ? parentFile.getParentFile() : null;
    String name = parentFile != null ? parentFile.getName() : "";
    if (name.contains("Program Files") && root != null) {
      String x86Suffix = " (x86)";
      boolean x86 = name.endsWith(x86Suffix) && name.length() > x86Suffix.length();
      File anotherJavasFolder;
      if (x86) {
        anotherJavasFolder = new File(root, name.substring(0, name.length() - x86Suffix.length()));
      }
      else {
        anotherJavasFolder = new File(root, name + x86Suffix);
      }
      if (anotherJavasFolder.isDirectory()) {
        scanFolder(new File(anotherJavasFolder, javasFolder.getName()), result);
      }
    }
    return result;
  }

  private static void scanFolder(File javasFolder, ArrayList<String> result) {
    File[] candidates = javasFolder.listFiles(new FileFilter() {
      @Override
      public boolean accept(File pathname) {
        return JdkUtil.checkForJdk(pathname);
      }
    });
    if (candidates != null) {
      result.addAll(ContainerUtil.map2List(candidates, new Function<File, String>() {
        @Override
        public String fun(File file) {
          return file.getAbsolutePath();
        }
      }));
    }
  }

  @Override
  public FileChooserDescriptor getHomeChooserDescriptor() {
    FileChooserDescriptor descriptor = super.getHomeChooserDescriptor();
    descriptor.putUserData(KEY, Boolean.TRUE);
    return descriptor;
  }

  @NonNls public static final String MAC_HOME_PATH = "/Home";

  @Override
  public String adjustSelectedSdkHome(String homePath) {
    if (SystemInfo.isMac) {
      File home = new File(homePath, MAC_HOME_PATH);
      if (home.exists()) return home.getPath();

      home = new File(new File(homePath, "Contents"), "Home");
      if (home.exists()) return home.getPath();
    }

    return homePath;
  }

  @Override
  public boolean isValidSdkHome(String path) {
    return checkForJdk(new File(path));
  }

  @Override
  public String suggestSdkName(String currentSdkName, String sdkHome) {
    final String suggestedName;
    if (currentSdkName != null && !currentSdkName.isEmpty()) {
      final Matcher matcher = myVersionStringPattern.matcher(currentSdkName);
      final boolean replaceNameWithVersion = matcher.matches();
      if (replaceNameWithVersion){
        // user did not change name -> set it automatically
        final String versionString = getVersionString(sdkHome);
        suggestedName = versionString == null ? currentSdkName : matcher.replaceFirst("$1" + versionString + "$3");
      }
      else {
        suggestedName = currentSdkName;
      }
    }
    else {
      String versionString = getVersionString(sdkHome);
      suggestedName = versionString == null ? ProjectBundle.message("sdk.java.unknown.name") : getVersionNumber(versionString);
    }
    return suggestedName;
  }

  @NotNull
  private static String getVersionNumber(@NotNull String versionString) {
    if (versionString.startsWith(JAVA_VERSION_PREFIX) || versionString.startsWith(OPENJDK_VERSION_PREFIX)) {
      boolean openJdk = versionString.startsWith(OPENJDK_VERSION_PREFIX);
      versionString = versionString.substring(openJdk ? OPENJDK_VERSION_PREFIX.length() : JAVA_VERSION_PREFIX.length());
      if (versionString.startsWith("\"") && versionString.endsWith("\"")) {
        versionString = versionString.substring(1, versionString.length() - 1);
      }
      int dotIdx = versionString.indexOf('.');
      if (dotIdx > 0) {
        try {
          int major = Integer.parseInt(versionString.substring(0, dotIdx));
          int minorDot = versionString.indexOf('.', dotIdx + 1);
          if (minorDot > 0) {
            int minor = Integer.parseInt(versionString.substring(dotIdx + 1, minorDot));
            versionString = major + "." + minor;
          }
        }
        catch (NumberFormatException e) {
          // Do nothing. Use original version string if failed to parse according to major.minor pattern.
        }
      }
    }
    return versionString;
  }

  @Override
  @SuppressWarnings({"HardCodedStringLiteral"})
  public void setupSdkPaths(@NotNull Sdk sdk) {
    final File jdkHome = new File(sdk.getHomePath());
    List<VirtualFile> classes = findClasses(jdkHome, false);
    VirtualFile sources = findSources(jdkHome);
    VirtualFile docs = findDocs(jdkHome, "docs/api");

    final SdkModificator sdkModificator = sdk.getSdkModificator();
    final Set<VirtualFile> previousRoots = new LinkedHashSet<VirtualFile>(Arrays.asList(sdkModificator.getRoots(OrderRootType.CLASSES)));
    sdkModificator.removeRoots(OrderRootType.CLASSES);
    previousRoots.removeAll(new HashSet<VirtualFile>(classes));
    for (VirtualFile aClass : classes) {
      sdkModificator.addRoot(aClass, OrderRootType.CLASSES);
    }
    for (VirtualFile root : previousRoots) {
      sdkModificator.addRoot(root, OrderRootType.CLASSES);
    }
    if(sources != null){
      sdkModificator.addRoot(sources, OrderRootType.SOURCES);
    }
    final VirtualFile javaFxSources = findSources(jdkHome, "javafx-src");
    if (javaFxSources != null) {
      sdkModificator.addRoot(javaFxSources, OrderRootType.SOURCES);
    }
    if(docs != null){
      sdkModificator.addRoot(docs, JavadocOrderRootType.getInstance());
    }
    else if (SystemInfo.isMac) {
      VirtualFile commonDocs = findDocs(jdkHome, "docs");
      if (commonDocs == null) {
        commonDocs = findInJar(new File(jdkHome, "docs.jar"), "doc/api");
        if (commonDocs == null) {
          commonDocs = findInJar(new File(jdkHome, "docs.jar"), "docs/api");
        }
      }
      if (commonDocs != null) {
        sdkModificator.addRoot(commonDocs, JavadocOrderRootType.getInstance());
      }

      VirtualFile appleDocs = findDocs(jdkHome, "appledocs");
      if (appleDocs == null) {
        appleDocs = findInJar(new File(jdkHome, "appledocs.jar"), "appledoc/api");
      }
      if (appleDocs != null) {
        sdkModificator.addRoot(appleDocs, JavadocOrderRootType.getInstance());
      }

      if (commonDocs == null && appleDocs == null && sources == null) {
        String url = getDefaultDocumentationUrl(sdk);
        if (url != null) {
          sdkModificator.addRoot(VirtualFileManager.getInstance().findFileByUrl(url), JavadocOrderRootType.getInstance());
        }
      }
    } else {
      if (getVersion(sdk) == JavaSdkVersion.JDK_1_7) {
        sdkModificator.addRoot(VirtualFileManager.getInstance().findFileByUrl("http://docs.oracle.com/javafx/2/api/"), JavadocOrderRootType.getInstance());
      }
    }
    attachJdkAnnotations(sdkModificator);
    sdkModificator.commitChanges();
  }

  public static void attachJdkAnnotations(@NotNull SdkModificator modificator) {
    LocalFileSystem lfs = LocalFileSystem.getInstance();
    // community idea under idea
    VirtualFile root = lfs.findFileByPath(FileUtil.toSystemIndependentName(PathManager.getHomePath()) + "/java/jdkAnnotations");

    if (root == null) {  // idea under idea
      root = lfs.findFileByPath(FileUtil.toSystemIndependentName(PathManager.getHomePath()) + "/community/java/jdkAnnotations");
    }
    if (root == null) { // build
      root = VirtualFileManager.getInstance().findFileByUrl("jar://"+ FileUtil.toSystemIndependentName(PathManager.getHomePath()) + "/lib/jdkAnnotations.jar!/");
    }
    if (root == null) {
      LOG.error("jdk annotations not found in: "+ FileUtil.toSystemIndependentName(PathManager.getHomePath()) + "/lib/jdkAnnotations.jar!/");
      return;
    }

    OrderRootType annoType = AnnotationOrderRootType.getInstance();
    modificator.removeRoot(root, annoType);
    modificator.addRoot(root, annoType);
  }

  private final Map<String, String> myCachedVersionStrings = new HashMap<String, String>();

  @Override
  public final String getVersionString(final String sdkHome) {
    if (myCachedVersionStrings.containsKey(sdkHome)) {
      return myCachedVersionStrings.get(sdkHome);
    }
    String versionString = getJdkVersion(sdkHome);
    if (versionString != null && versionString.isEmpty()) {
      versionString = null;
    }

    if (versionString != null){
      myCachedVersionStrings.put(sdkHome, versionString);
    }

    return versionString;
  }

  @Override
  public int compareTo(@NotNull String versionString, @NotNull String versionNumber) {
    return getVersionNumber(versionString).compareTo(versionNumber);
  }

  @Override
  public JavaSdkVersion getVersion(@NotNull Sdk sdk) {
    String version = sdk.getVersionString();
    if (version == null) return null;
    return JdkVersionUtil.getVersion(version);
  }

  @Override
  @Nullable
  public JavaSdkVersion getVersion(@NotNull String versionString) {
    return JdkVersionUtil.getVersion(versionString);
  }

  @Override
  public boolean isOfVersionOrHigher(@NotNull Sdk sdk, @NotNull JavaSdkVersion version) {
    JavaSdkVersion sdkVersion = getVersion(sdk);
    return sdkVersion != null && sdkVersion.isAtLeast(version);
  }

  @Override
  public Sdk createJdk(@NotNull String jdkName, @NotNull String home, boolean isJre) {
    ProjectJdkImpl jdk = new ProjectJdkImpl(jdkName, this);
    SdkModificator sdkModificator = jdk.getSdkModificator();

    String path = home.replace(File.separatorChar, '/');
    sdkModificator.setHomePath(path);
    sdkModificator.setVersionString(jdkName); // must be set after home path, otherwise setting home path clears the version string

    File jdkHomeFile = new File(home);
    addClasses(jdkHomeFile, sdkModificator, isJre);
    addSources(jdkHomeFile, sdkModificator);
    addDocs(jdkHomeFile, sdkModificator);
    sdkModificator.commitChanges();

    return jdk;
  }

  private static void addClasses(File file, SdkModificator sdkModificator, boolean isJre) {
    for (VirtualFile virtualFile : findClasses(file, isJre)) {
      sdkModificator.addRoot(virtualFile, OrderRootType.CLASSES);
    }
  }

  private static List<VirtualFile> findClasses(File file, boolean isJre) {
    List<VirtualFile> result = ContainerUtil.newArrayList();

    List<File> rootFiles = JavaSdkUtil.getJdkClassesRoots(file, isJre);
    for (File child : rootFiles) {
      String url = VfsUtil.getUrlForLibraryRoot(child);
      VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(url);
      if (vFile != null) {
        result.add(vFile);
      }
    }

    return result;
  }

  private static void addSources(File file, SdkModificator sdkModificator) {
    VirtualFile vFile = findSources(file);
    if (vFile != null) {
      sdkModificator.addRoot(vFile, OrderRootType.SOURCES);
    }
  }

  @Nullable
  @SuppressWarnings({"HardCodedStringLiteral"})
  public static VirtualFile findSources(File file) {
    return findSources(file, "src");
  }

  @Nullable
  @SuppressWarnings({"HardCodedStringLiteral"})
  public static VirtualFile findSources(File file, final String srcName) {
    File srcDir = new File(file, "src");
    File jarFile = new File(file, srcName + ".jar");
    if (!jarFile.exists()) {
      jarFile = new File(file, srcName + ".zip");
    }

    if (jarFile.exists()) {
      VirtualFile vFile = findInJar(jarFile, "src");
      if (vFile != null) return vFile;
      // try 1.4 format
      vFile = findInJar(jarFile, "");
      return vFile;
    }
    else {
      if (!srcDir.exists() || !srcDir.isDirectory()) return null;
      String path = srcDir.getAbsolutePath().replace(File.separatorChar, '/');
      return LocalFileSystem.getInstance().findFileByPath(path);
    }
  }

  @SuppressWarnings({"HardCodedStringLiteral"})
  private static void addDocs(File file, SdkModificator rootContainer) {
    VirtualFile vFile = findDocs(file, "docs/api");
    if (vFile != null) {
      rootContainer.addRoot(vFile, JavadocOrderRootType.getInstance());
    }
  }

  @Nullable
  private static VirtualFile findInJar(File jarFile, String relativePath) {
    if (!jarFile.exists()) return null;
    String url = JarFileSystem.PROTOCOL_PREFIX +
                 jarFile.getAbsolutePath().replace(File.separatorChar, '/') + JarFileSystem.JAR_SEPARATOR + relativePath;
    return VirtualFileManager.getInstance().findFileByUrl(url);
  }

  @Nullable
  public static VirtualFile findDocs(File file, final String relativePath) {
    file = new File(file.getAbsolutePath() + File.separator + relativePath.replace('/', File.separatorChar));
    if (!file.exists() || !file.isDirectory()) return null;
    String path = file.getAbsolutePath().replace(File.separatorChar, '/');
    return LocalFileSystem.getInstance().findFileByPath(path);
  }

  @Override
  public boolean isRootTypeApplicable(OrderRootType type) {
    return type == OrderRootType.CLASSES ||
           type == OrderRootType.SOURCES ||
           type == JavadocOrderRootType.getInstance() ||
           type == AnnotationOrderRootType.getInstance();
  }
}
