/*
 * 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.jetbrains.python.packaging;

import com.intellij.execution.ExecutionException;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.vfs.VirtualFile;
import com.jetbrains.python.packaging.ui.PyCondaManagementService;
import com.jetbrains.python.packaging.ui.PyPackageManagementService;
import com.jetbrains.python.psi.LanguageLevel;
import com.jetbrains.python.sdk.PythonSdkType;
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

/**
 * @author yole
 */
public class PyPackageManagersImpl extends PyPackageManagers {
  private final Map<String, PyPackageManagerImpl> myInstances = new HashMap<>();

  @NotNull
  public synchronized PyPackageManager forSdk(@NotNull final Sdk sdk) {
    final String homePath = sdk.getHomePath();
    if (homePath == null) {
      return new DummyPackageManager(sdk);
    }
    PyPackageManagerImpl manager = myInstances.get(homePath);
    if (manager == null) {
      if (PythonSdkType.isRemote(sdk)) {
        manager = new PyRemotePackageManagerImpl(sdk);
      }
      else if (PyCondaPackageManagerImpl.isCondaVEnv(sdk) && PyCondaPackageService.getCondaExecutable(sdk.getHomeDirectory()) != null) {
        manager = new PyCondaPackageManagerImpl(sdk);
      }
      else {
        manager = new PyPackageManagerImpl(sdk);
      }
      if (sdkIsSetUp(sdk))
        myInstances.put(homePath, manager);
    }
    return manager;
  }

  private static boolean sdkIsSetUp(@NotNull final Sdk sdk) {
    final VirtualFile[] roots = sdk.getRootProvider().getFiles(OrderRootType.CLASSES);
    return roots.length != 0;
  }

  public PyPackageManagementService getManagementService(Project project, Sdk sdk) {
    if (PyCondaPackageManagerImpl.isCondaVEnv(sdk)) {
      return new PyCondaManagementService(project, sdk);
    }
    return new PyPackageManagementService(project, sdk);
  }

  @Override
  public void clearCache(@NotNull Sdk sdk) {
    if (myInstances.containsKey(sdk.getHomePath())) {
      myInstances.remove(sdk.getHomePath());
    }
  }

  static class DummyPackageManager extends PyPackageManager {
    private final String myName;
    private final LanguageLevel myLanguageLevel;
    private final PythonSdkFlavor myFlavor;

    public DummyPackageManager(@NotNull final Sdk sdk) {
      myName = sdk.getName();
      myLanguageLevel = PythonSdkType.getLanguageLevelForSdk(sdk);
      myFlavor = PythonSdkFlavor.getFlavor(sdk);
    }

    @Override
    public void installManagement() throws ExecutionException {
      throw new ExecutionException(getErrorMessage());
    }

    @Override
    public boolean hasManagement() throws ExecutionException {
      return false;
    }

    @NotNull
    private String getErrorMessage() {
      return "Invalid interpreter \"" + myName + "\" version: " + myLanguageLevel.toString() + " type: " + myFlavor.getName();
    }

    @Override
    public void install(@NotNull String requirementString) throws ExecutionException {
      throw new ExecutionException(getErrorMessage());
    }

    @Override
    public void install(@NotNull List<PyRequirement> requirements, @NotNull List<String> extraArgs) throws ExecutionException {
      throw new ExecutionException(getErrorMessage());
    }

    @Override
    public void uninstall(@NotNull List<PyPackage> packages) throws ExecutionException {
      throw new ExecutionException(getErrorMessage());
    }

    @Override
    public void refresh() {
    }

    @NotNull
    @Override
    public String createVirtualEnv(@NotNull String destinationDir, boolean useGlobalSite) throws ExecutionException {
      throw new ExecutionException(getErrorMessage());
    }

    @Nullable
    @Override
    public List<PyPackage> getPackages() {
      return null;
    }

    @NotNull
    @Override
    public List<PyPackage> refreshAndGetPackages(boolean alwaysRefresh) throws ExecutionException {
      throw new ExecutionException(getErrorMessage());
    }

    @Nullable
    @Override
    public List<PyRequirement> getRequirements(@NotNull Module module) {
      return null;
    }

    @NotNull
    @Override
    public Set<PyPackage> getDependents(@NotNull PyPackage pkg) throws ExecutionException {
      throw new ExecutionException(getErrorMessage());
    }
  }

}

@@ -639,101 +639,8 @@
 g;%0A%0A
-import com.intellij.execution.ExecutionException;%0Aimport com.intellij.openapi.module.Module;%0A
 impo
@@ -988,129 +988,25 @@
 hon.
-psi.LanguageLevel;%0Aimport com.jetbrains.python.sdk.PythonSdkType;%0Aimport com.jetbrains.python.sdk.flavors.PythonSdkFlavor
+sdk.PythonSdkType
 ;%0Aim
@@ -1049,51 +1049,34 @@
 ll;%0A
+%0A
 import 
-org.jetbrains.annotations.Nullable;%0A
+java.util.HashMap;
 %0Aimp
@@ -1089,17 +1089,19 @@
 va.util.
-*
+Map
 ;%0A%0A/**%0A 
@@ -1368,114 +1368,43 @@
 ing 
-homePath = sdk.getHomePath();%0A    if (homePath == null) %7B%0A      return new DummyPackageManager(sdk);%0A    %7D
+key = PythonSdkType.getSdkKey(sdk);
 %0A   
@@ -1451,24 +1451,19 @@
 ces.get(
-homePath
+key
 );%0A    i
@@ -1912,16 +1912,11 @@
 put(
-homePath
+key
 , ma
@@ -2467,2315 +2467,125 @@
     
-if (myInstances.containsKey(sdk.getHomePath())) %7B%0A      myInstances.remove(sdk.getHomePath());%0A    %7D%0A  %7D%0A%0A  static class DummyPackageManager extends PyPackageManager %7B%0A    private final String myName;%0A    private final LanguageLevel myLanguageLevel;%0A    private final PythonSdkFlavor myFlavor;%0A%0A    public DummyPackageManager(@NotNull final Sdk sdk) %7B%0A      myName = sdk.getName();%0A      myLanguageLevel = PythonSdkType.getLanguageLevelForSdk(sdk);%0A      myFlavor = PythonSdkFlavor.getFlavor(sdk);%0A    %7D%0A%0A    @Override%0A    public void installManagement() throws ExecutionException %7B%0A      throw new ExecutionException(getErrorMessage());%0A    %7D%0A%0A    @Override%0A    public boolean hasManagement() throws ExecutionException %7B%0A      return false;%0A    %7D%0A%0A    @NotNull%0A    private String getErrorMessage() %7B%0A      return %22Invalid interpreter %5C%22%22 + myName + %22%5C%22 version: %22 + myLanguageLevel.toString() + %22 type: %22 + myFlavor.getName();%0A    %7D%0A%0A    @Override%0A    public void install(@NotNull String requirementString) throws ExecutionException %7B%0A      throw new ExecutionException(getErrorMessage());%0A    %7D%0A%0A    @Override%0A    public void install(@NotNull List%3CPyRequirement%3E requirements, @NotNull List%3CString%3E extraArgs) throws ExecutionException %7B%0A      throw new ExecutionException(getErrorMessage());%0A    %7D%0A%0A    @Override%0A    public void uninstall(@NotNull List%3CPyPackage%3E packages) throws ExecutionException %7B%0A      throw new ExecutionException(getErrorMessage());%0A    %7D%0A%0A    @Override%0A    public void refresh() %7B%0A    %7D%0A%0A    @NotNull%0A    @Override%0A    public String createVirtualEnv(@NotNull String destinationDir, boolean useGlobalSite) throws ExecutionException %7B%0A      throw new ExecutionException(getErrorMessage());%0A    %7D%0A%0A    @Nullable%0A    @Override%0A    public List%3CPyPackage%3E getPackages() %7B%0A      return null;%0A    %7D%0A%0A    @NotNull%0A    @Override%0A    public List%3CPyPackage%3E refreshAndGetPackages(boolean alwaysRefresh) throws ExecutionException %7B%0A      throw new ExecutionException(getErrorMessage());%0A    %7D%0A%0A    @Nullable%0A    @Override%0A    public List%3CPyRequirement%3E getRequirements(@NotNull Module module) %7B%0A      return null;%0A    %7D%0A%0A    @NotNull%0A    @Override%0A    public Set%3CPyPackage%3E getDependents(@NotNull PyPackage pkg) throws ExecutionException %7B%0A      throw new ExecutionException(getErrorMessage()
+final String key = PythonSdkType.getSdkKey(sdk);%0A    if (myInstances.containsKey(key)) %7B%0A      myInstances.remove(key
 );%0A 
@@ -2593,11 +2593,10 @@
   %7D%0A  %7D%0A
-%0A
 %7D%0A

Use Python SDK name as key instead of home path (PY-18785)