/*
 * 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 org.jetbrains.idea.svn.mergeinfo;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.idea.svn.SvnPropertyKeys;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.history.SvnChangeList;
import org.jetbrains.idea.svn.info.Info;
import org.jetbrains.idea.svn.properties.PropertyValue;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNMergeRange;
import org.tmatesoft.svn.core.SVNMergeRangeList;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.util.SVNMergeInfoUtil;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;

import java.io.File;
import java.util.*;

public class BranchInfo {
  private final static Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.mergeinfo.BranchInfo");
  // repo path in branch in format path@revision -> merged revisions
  private final Map<String, Set<Long>> myPathMergedMap;
  private final Map<String, Set<Long>> myNonInheritablePathMergedMap;

  private boolean myMixedRevisionsFound;

  // revision in trunk -> whether merged into branch
  private final Map<Long, SvnMergeInfoCache.MergeCheckResult> myAlreadyCalculatedMap;
  private final Object myCalculatedLock = new Object();

  private final String myRepositoryRoot;
  private final String myBranchUrl;
  private final String myTrunkUrl;
  private final String myTrunkCorrected;
  private final SvnVcs myVcs;

  private SvnMergeInfoCache.CopyRevison myCopyRevison;
  private final MultiMap<Long, String> myPartlyMerged;

  public BranchInfo(final SvnVcs vcs, final String repositoryRoot, final String branchUrl, final String trunkUrl,
                    final String trunkCorrected) {
    myVcs = vcs;
    myRepositoryRoot = repositoryRoot;
    myBranchUrl = branchUrl;
    myTrunkUrl = trunkUrl;
    myTrunkCorrected = trunkCorrected;

    myPathMergedMap = new HashMap<String, Set<Long>>();
    myPartlyMerged = new MultiMap<Long, String>();
    myNonInheritablePathMergedMap = new HashMap<String, Set<Long>>();

    myAlreadyCalculatedMap = new HashMap<Long, SvnMergeInfoCache.MergeCheckResult>();
  }

  private long calculateCopyRevision(final String branchPath) {
    if (myCopyRevison != null && Comparing.equal(myCopyRevison.getPath(), branchPath)) {
      return myCopyRevison.getRevision();
    }
    myCopyRevison = new SvnMergeInfoCache.CopyRevison(myVcs, branchPath, myRepositoryRoot, myBranchUrl, myTrunkUrl);
    return -1;
  }

  public void clear() {
    myPathMergedMap.clear();
    synchronized (myCalculatedLock) {
      myAlreadyCalculatedMap.clear();
    }
    myMixedRevisionsFound = false;
  }

  public void halfClear(final long listNumber) {
    myPathMergedMap.clear();
    synchronized (myCalculatedLock) {
      myAlreadyCalculatedMap.remove(listNumber);
    }
    myMixedRevisionsFound = false;
  }

  public MergeinfoCached getCached() {
    synchronized (myCalculatedLock) {
      final long revision;
      if (myCopyRevison != null && myCopyRevison.getRevision() != -1) {
        revision = myCopyRevison.getRevision();
      } else {
        revision = -1;
      }
      return new MergeinfoCached(Collections.unmodifiableMap(myAlreadyCalculatedMap), revision);
    }
  }

  public SvnMergeInfoCache.MergeCheckResult checkList(final SvnChangeList list, final String branchPath) {
    synchronized (myCalculatedLock) {
      final long revision = calculateCopyRevision(branchPath);
      if (revision != -1 && revision >= list.getNumber()) {
        return SvnMergeInfoCache.MergeCheckResult.COMMON;
      }

      final SvnMergeInfoCache.MergeCheckResult calculated = myAlreadyCalculatedMap.get(list.getNumber());
      if (calculated != null) {
        return calculated;
      }

      final SvnMergeInfoCache.MergeCheckResult result = checkAlive(list, branchPath);
      myAlreadyCalculatedMap.put(list.getNumber(), result);
      return result;
    }
  }

  private SvnMergeInfoCache.MergeCheckResult checkAlive(final SvnChangeList list, final String branchPath) {
    final Info info = getInfo(new File(branchPath));
    if (info == null || info.getURL() == null || (! SVNPathUtil.isAncestor(myBranchUrl, info.getURL().toString()))) {
      return SvnMergeInfoCache.MergeCheckResult.NOT_MERGED;
    }
    final String subPathUnderBranch = SVNPathUtil.getRelativePath(myBranchUrl, info.getURL().toString());

    final MultiMap<SvnMergeInfoCache.MergeCheckResult, String> result = new MultiMap<SvnMergeInfoCache.MergeCheckResult, String>();
    checkPaths(list.getNumber(), list.getAddedPaths(), branchPath, subPathUnderBranch, result);
    if (result.containsKey(SvnMergeInfoCache.MergeCheckResult.NOT_EXISTS)) {
      return SvnMergeInfoCache.MergeCheckResult.NOT_EXISTS;
    }
    checkPaths(list.getNumber(), list.getDeletedPaths(), branchPath, subPathUnderBranch, result);
    if (result.containsKey(SvnMergeInfoCache.MergeCheckResult.NOT_EXISTS)) {
      return SvnMergeInfoCache.MergeCheckResult.NOT_EXISTS;
    }
    checkPaths(list.getNumber(), list.getChangedPaths(), branchPath, subPathUnderBranch, result);

    if (result.containsKey(SvnMergeInfoCache.MergeCheckResult.NOT_EXISTS)) {
      return SvnMergeInfoCache.MergeCheckResult.NOT_EXISTS;
    } else if (result.containsKey(SvnMergeInfoCache.MergeCheckResult.NOT_MERGED)) {
      myPartlyMerged.put(list.getNumber(), result.get(SvnMergeInfoCache.MergeCheckResult.NOT_MERGED));
      return SvnMergeInfoCache.MergeCheckResult.NOT_MERGED;
    }
    return SvnMergeInfoCache.MergeCheckResult.MERGED;
  }

  private void checkPaths(final long number, final Collection<String> paths, final String branchPath, final String subPathUnderBranch,
                          final MultiMap<SvnMergeInfoCache.MergeCheckResult, String> result) {
    final String myTrunkPathCorrespondingToLocalBranchPath = SVNPathUtil.append(myTrunkCorrected, subPathUnderBranch);
    for (String path : paths) {
      final String absoluteInTrunkPath = SVNPathUtil.append(myRepositoryRoot, path);
      if (! absoluteInTrunkPath.startsWith(myTrunkPathCorrespondingToLocalBranchPath)) {
        result.putValue(SvnMergeInfoCache.MergeCheckResult.NOT_EXISTS, path);
        continue;
      }
      final String relativeToTrunkPath = absoluteInTrunkPath.substring(myTrunkPathCorrespondingToLocalBranchPath.length());
      final String localPathInBranch = new File(branchPath, relativeToTrunkPath).getAbsolutePath();
      
      final SvnMergeInfoCache.MergeCheckResult pathResult = checkPathGoingUp(number, -1, branchPath, localPathInBranch, path, true);
      result.putValue(pathResult, path);
    }
  }

  private SvnMergeInfoCache.MergeCheckResult goUp(final long revisionAsked, final long targetRevision, final String branchRootPath,
                                                              final String path, final String trunkUrl) {
    final String newTrunkUrl = SVNPathUtil.removeTail(trunkUrl).trim();
    if (newTrunkUrl.length() == 0 || "/".equals(newTrunkUrl)) {
      return SvnMergeInfoCache.MergeCheckResult.NOT_MERGED;
    }
    final String newPath = new File(path).getParent();
    if (newPath.length() < branchRootPath.length()) {
      // we are higher than WC root -> go into repo only
      if (targetRevision == -1) {
        // no paths in local copy
        return SvnMergeInfoCache.MergeCheckResult.NOT_EXISTS;
      }
      final Info svnInfo = getInfo(new File(branchRootPath));
      if (svnInfo == null || svnInfo.getRevision() == null || svnInfo.getURL() == null) {
        return SvnMergeInfoCache.MergeCheckResult.NOT_MERGED;
      }
      try {
        return goUpInRepo(revisionAsked, targetRevision, svnInfo.getURL().removePathTail(), newTrunkUrl);
      }
      catch (SVNException e) {
        LOG.info(e);
        return SvnMergeInfoCache.MergeCheckResult.NOT_MERGED;
      }
    }
    
    return checkPathGoingUp(revisionAsked, targetRevision, branchRootPath, newPath, newTrunkUrl, false);
  }

  private SvnMergeInfoCache.MergeCheckResult goUpInRepo(final long revisionAsked, final long targetRevision, final SVNURL branchUrl,
                                                        final String trunkUrl) {
    final String branchAsString = branchUrl.toString();
    final String keyString = branchAsString + "@" + targetRevision;
    final Set<Long> mergeInfo = myPathMergedMap.get(keyString);
    if (mergeInfo != null) {
      // take from self or first parent with info; do not go further
      return SvnMergeInfoCache.MergeCheckResult.getInstance(mergeInfo.contains(revisionAsked));
    }

    final PropertyValue mergeinfoProperty;
    SvnTarget target = SvnTarget.fromURL(branchUrl);

    try {
      mergeinfoProperty = myVcs.getFactory(target).createPropertyClient().getProperty(target, SvnPropertyKeys.MERGE_INFO, false,
                                                                                      SVNRevision.create(targetRevision));
    }
    catch (VcsException e) {
      LOG.info(e);
      return SvnMergeInfoCache.MergeCheckResult.NOT_MERGED;
    }

    if (mergeinfoProperty == null) {
      final String newTrunkUrl = SVNPathUtil.removeTail(trunkUrl).trim();
      final SVNURL newBranchUrl;
      try {
        newBranchUrl = branchUrl.removePathTail();
      }
      catch (SVNException e) {
        LOG.info(e);
        return SvnMergeInfoCache.MergeCheckResult.NOT_MERGED;
      }
      final String absoluteTrunk = SVNPathUtil.append(myRepositoryRoot, newTrunkUrl);
      if ((1 >= newTrunkUrl.length()) || (myRepositoryRoot.length() >= newBranchUrl.toString().length()) ||
        (newBranchUrl.toString().equals(absoluteTrunk))) {
        return SvnMergeInfoCache.MergeCheckResult.NOT_MERGED;
      }
      // go up
      return goUpInRepo(revisionAsked, targetRevision, newBranchUrl, newTrunkUrl);
    }
    // process
    return processMergeinfoProperty(keyString, revisionAsked, mergeinfoProperty, trunkUrl, false);
  }

  private Info getInfo(final File pathFile) {
    return myVcs.getInfo(pathFile);
  }

  private SvnMergeInfoCache.MergeCheckResult checkPathGoingUp(final long revisionAsked, final long targetRevision, final String branchRootPath,
                                                              final String path, final String trunkUrl, final boolean self) {
    final File pathFile = new File(path);

    if (targetRevision == -1) {
      // we didn't find existing item on the path jet
      // check whether we locally have path
      if (! pathFile.exists()) {
        // go into parent
        return goUp(revisionAsked, targetRevision, branchRootPath, path, trunkUrl);
      }
    }
    
    final Info svnInfo = getInfo(pathFile);
    if (svnInfo == null || svnInfo.getRevision() == null || svnInfo.getURL() == null) {
      LOG.info("Svninfo for " + pathFile + " is null or not full.");
      return SvnMergeInfoCache.MergeCheckResult.NOT_MERGED;
    }

    final long actualRevision = svnInfo.getRevision().getNumber();
    final long targetRevisionCorrected = (targetRevision == -1) ? actualRevision : targetRevision;
    
    // here we know local URL and revision

    // check existing info
    final String keyString = path + "@" + targetRevisionCorrected;
    final Set<Long> selfInfo = self ? myNonInheritablePathMergedMap.get(keyString) : null;
    final Set<Long> mergeInfo = myPathMergedMap.get(keyString);
    if (mergeInfo != null || selfInfo != null) {
      final boolean merged = ((mergeInfo != null) && mergeInfo.contains(revisionAsked)) ||
                             ((selfInfo != null) && selfInfo.contains(revisionAsked));
      // take from self or first parent with info; do not go further 
      return SvnMergeInfoCache.MergeCheckResult.getInstance(merged);
    }

    final PropertyValue mergeinfoProperty;
    try {
      if (actualRevision == targetRevisionCorrected) {
        // look in WC
        SvnTarget target = SvnTarget.fromFile(pathFile, SVNRevision.WORKING);
        mergeinfoProperty =
          myVcs.getFactory(target).createPropertyClient().getProperty(target, SvnPropertyKeys.MERGE_INFO, false, SVNRevision.WORKING);
      } else {
        // in repo
        myMixedRevisionsFound = true;
        SvnTarget target = SvnTarget.fromURL(svnInfo.getURL());
        mergeinfoProperty = myVcs.getFactory(target).createPropertyClient()
          .getProperty(target, SvnPropertyKeys.MERGE_INFO, false, SVNRevision.create(targetRevisionCorrected));
      }
    }
    catch (VcsException e) {
      LOG.info(e);
      return SvnMergeInfoCache.MergeCheckResult.NOT_MERGED;
    }

    if (mergeinfoProperty == null) {
      // go up
      return goUp(revisionAsked, targetRevisionCorrected, branchRootPath, path, trunkUrl);
    }
    // process
    return processMergeinfoProperty(keyString, revisionAsked, mergeinfoProperty, trunkUrl, self);
  }

  private SvnMergeInfoCache.MergeCheckResult processMergeinfoProperty(final String pathWithRevisionNumber, final long revisionAsked,
                                                                      final PropertyValue value, final String trunkRelativeUrl,
                                                                      final boolean self) {
    final String valueAsString = value.toString().trim();

    // empty mergeinfo
    if (valueAsString.length() == 0) {
      myPathMergedMap.put(pathWithRevisionNumber, Collections.<Long>emptySet());
      return SvnMergeInfoCache.MergeCheckResult.NOT_MERGED;
    }

    final Map<String, SVNMergeRangeList> map;
    try {
      map = SVNMergeInfoUtil.parseMergeInfo(new StringBuffer(replaceSeparators(value.toString())), null);
    }
    catch (SVNException e) {
      LOG.info(e);
      return SvnMergeInfoCache.MergeCheckResult.NOT_MERGED;
    }

    for (String key : map.keySet()) {
      if ((key != null) && (trunkRelativeUrl.startsWith(key))) {
        final Set<Long> revisions = new HashSet<Long>();
        final Set<Long> nonInheritableRevisions = new HashSet<Long>();

        final SVNMergeRangeList rangesList = map.get(key);

        boolean result = false;
        for (SVNMergeRange range : rangesList.getRanges()) {
          // SVN does not include start revision in range
          final long startRevision = range.getStartRevision() + 1;
          final long endRevision = range.getEndRevision();
          final boolean isInheritable = range.isInheritable();
          final boolean inInterval = (revisionAsked >= startRevision) && (revisionAsked <= endRevision);

          if ((isInheritable || self) && inInterval) {
            result = true;
          }

          for (long i = startRevision; i <= endRevision; i++) {
            if (isInheritable) {
              revisions.add(i);
            } else {
              nonInheritableRevisions.add(i);
            }
          }
        }
        myPathMergedMap.put(pathWithRevisionNumber, revisions);
        if (! nonInheritableRevisions.isEmpty()) {
          myNonInheritablePathMergedMap.put(pathWithRevisionNumber, nonInheritableRevisions);
        }

        return SvnMergeInfoCache.MergeCheckResult.getInstance(result);
      }
    }
    myPathMergedMap.put(pathWithRevisionNumber, Collections.<Long>emptySet());
    return SvnMergeInfoCache.MergeCheckResult.NOT_MERGED;
  }

  private String replaceSeparators(final String s) {
    return s.replace('\r', '\n').replace("\n\n", "\n");
  }

  public boolean isMixedRevisionsFound() {
    return myMixedRevisionsFound;
  }

  // if nothing, maybe all not merged or merged: here only partly not merged
  public Collection<String> getNotMergedPaths(final long number) {
    return myPartlyMerged.get(number);
  }

  public static class MyMergeCheckerWrapper implements MergeChecker {
    private final BranchInfo myInfo;
    private final String myBranchPath;

    public MyMergeCheckerWrapper(String branchPath, BranchInfo info) {
      myBranchPath = branchPath;
      myInfo = info;
    }

    public SvnMergeInfoCache.MergeCheckResult checkList(SvnChangeList list) {
      return myInfo.checkList(list, myBranchPath);
    }

    public Collection<String> getNotMergedPaths(long number) {
      return myInfo.getNotMergedPaths(number);
    }
  }
}
