/*
 * Copyright 2000-2009 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.vcs.changes.committed;

import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.NotNullFunction;
import com.intellij.util.PairProcessor;
import com.intellij.util.containers.ConcurrentHashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class CachesHolder {
  @NonNls private static final String VCS_CACHE_PATH = "vcsCache";
  
  private final Project myProject;
  private final Map<String, ChangesCacheFile> myCacheFiles;
  private final RepositoryLocationCache myLocationCache;
  private final ProjectLevelVcsManager myPlManager;

  public CachesHolder(final Project project, final RepositoryLocationCache locationCache) {
    myProject = project;
    myLocationCache = locationCache;
    myPlManager = ProjectLevelVcsManager.getInstance(myProject);
    myCacheFiles = new ConcurrentHashMap<String, ChangesCacheFile>();
  }

  public CachesHolder(final Project project, final RepositoryLocationCache locationCache, final ProjectLevelVcsManager manager) {
    myProject = project;
    myPlManager = manager;
    myLocationCache = locationCache;
    myCacheFiles = new ConcurrentHashMap<String, ChangesCacheFile>();
  }

  /**
   * Returns all paths that will be used to collect committed changes about. ideally, for one checkout there should be one file
   */
  public Map<VirtualFile, RepositoryLocation> getAllRootsUnderVcs(final AbstractVcs vcs) {
    final RootsCalculator calculator = new RootsCalculator(myProject, vcs, myLocationCache);
    return calculator.getRoots();
  }

  public void iterateAllRepositoryLocations(final PairProcessor<RepositoryLocation, AbstractVcs> locationProcessor) {
    final AbstractVcs[] vcses = myPlManager.getAllActiveVcss();
    for (AbstractVcs vcs : vcses) {
      final CommittedChangesProvider provider = vcs.getCommittedChangesProvider();
      if (provider instanceof CachingCommittedChangesProvider) {
        final Map<VirtualFile, RepositoryLocation> map = getAllRootsUnderVcs(vcs);
        for (VirtualFile root : map.keySet()) {
          final RepositoryLocation location = map.get(root);
          if (! Boolean.TRUE.equals(locationProcessor.process(location, vcs))) {
            return;
          }
        }
      }
    }
  }

  public void iterateAllCaches(final NotNullFunction<ChangesCacheFile, Boolean> consumer) {
    final AbstractVcs[] vcses = myPlManager.getAllActiveVcss();
    for (AbstractVcs vcs : vcses) {
      final CommittedChangesProvider provider = vcs.getCommittedChangesProvider();
      if (provider instanceof CachingCommittedChangesProvider) {
        final Map<VirtualFile, RepositoryLocation> map = getAllRootsUnderVcs(vcs);
        for (VirtualFile root : map.keySet()) {
          final RepositoryLocation location = map.get(root);
          final ChangesCacheFile cacheFile = getCacheFile(vcs, root, location);
          if (Boolean.TRUE.equals(consumer.fun(cacheFile))) {
            return;
          }
        }
      }
    }
  }

  public void clearAllCaches() {
    for (Map.Entry<String, ChangesCacheFile> entry : myCacheFiles.entrySet()) {
      entry.getValue().delete();
    }
    myCacheFiles.clear();
  }

  public List<ChangesCacheFile> getAllCaches() {
    final List<ChangesCacheFile> result = new ArrayList<ChangesCacheFile>();
    iterateAllCaches(new NotNullFunction<ChangesCacheFile, Boolean>() {
      @NotNull
      public Boolean fun(final ChangesCacheFile changesCacheFile) {
        result.add(changesCacheFile);
        return false;
      }
    });
    return result;
  }

  public ChangesCacheFile getCacheFile(AbstractVcs vcs, VirtualFile root, RepositoryLocation location) {
    final String key = location.getKey();
    ChangesCacheFile cacheFile = myCacheFiles.get(key);
    if (cacheFile == null) {
      cacheFile = new ChangesCacheFile(myProject, getCachePath(location), vcs, root, location);
      myCacheFiles.put(key, cacheFile);
    }
    return cacheFile;
  }

  public File getCacheBasePath() {
    File file = new File(PathManager.getSystemPath(), VCS_CACHE_PATH);
    file = new File(file, myProject.getLocationHash());
    return file;
  }

  @SuppressWarnings({"HardCodedStringLiteral"})
  private File getCachePath(final RepositoryLocation location) {
    File file = getCacheBasePath();
    file.mkdirs();
    String s = location.getKey();
    try {
      final byte[] bytes = MessageDigest.getInstance("MD5").digest(CharsetToolkit.getUtf8Bytes(s));
      StringBuilder result = new StringBuilder();
      for (byte aByte : bytes) {
        result.append(String.format("%02x", aByte));
      }
      return new File(file, result.toString());
    }
    catch (NoSuchAlgorithmException e) {
      throw new RuntimeException(e);
    }
  }

  public ChangesCacheFile haveCache(RepositoryLocation location) {
    String key = location.getKey();
    if (myCacheFiles.containsKey(key)) return myCacheFiles.get(key);
    key = key.endsWith("/") ? key : (key + "/");
    for (String s : myCacheFiles.keySet()) {
      if (key.startsWith(s) || s.startsWith(key)) return myCacheFiles.get(s);
    }
    return null;
  }
}
