package jetbrains.mps.ide.vfs;

import com.intellij.openapi.vfs.JarFileSystem;
import jetbrains.mps.ide.platform.watching.WatchedRoots;
import jetbrains.mps.vfs.FileSystemListener;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.jetbrains.annotations.NotNull;

import java.util.HashMap;
import java.util.Map;

/**
 * This is a FileSystemProvider for workbench. It differs from basic IdeaFSProvider
 * only in that it provides watching those paths for which listener was added.
 * In idea plugin it shouldn't be needed, as idea adds watch requests on its own. It does that
 * for source roots of modules. And our model roots must always be idea source roots, see MPS-18162
 * TODO does it make sense to have IdeaFileSystemProvider separately? merge
 *
 * danilla 8/7/13
 */
public class WatchingIdeaFileSystem extends IdeaFileSystem {
  private static final Logger LOG = LogManager.getLogger(WatchingIdeaFileSystem.class);
  private final WatchedRoots myWatchedRoots;

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

  public WatchingIdeaFileSystem(@NotNull WatchedRoots watchedRoots) {
    myWatchedRoots = watchedRoots;
  }

  @Override
  public void addListener(@NotNull FileSystemListener listener) {
    if (listener.getFileToListen() == null) return;
    if (myListenerToPathMap.containsKey(listener)) {
      LOG.warn("Trying to add the same listener again " + listener);
    }
    super.addListener(listener);
    @NotNull String path = lfsPath(listener.getFileToListen().getPath());
    boolean success = myWatchedRoots.addWatchRequest(path);
    if (success) {
      myListenerToPathMap.put(listener, path);
    }
  }

  @Override
  public void removeListener(@NotNull FileSystemListener listener) {
    if (listener.getFileToListen() == null) return;
    String path = myListenerToPathMap.get(listener);
    if (path != null) {
      myWatchedRoots.removeWatchRequest(path);
    }
    super.removeListener(listener);
  }

  private String lfsPath(@NotNull String path) {
    int jarRootIdx = path.indexOf(JarFileSystem.JAR_SEPARATOR);
    return jarRootIdx < 0 ? path : path.substring(0, jarRootIdx);
  }

  @NotNull
  @Override
  public String getComponentName() {
    return "IdeaFileSystemProvider with local fs watching";
  }
}
