/*
 * Copyright 2000-2012 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.svnkit.lowLevel;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Pair;
import com.intellij.util.ThrowableConsumer;
import com.intellij.util.ThrowableConvertor;
import com.intellij.util.containers.hash.HashSet;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.io.SVNRepository;

import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * User: Irina.Chernushina
 * Date: 7/30/12
 * Time: 3:39 PM
 */
public class CachingSvnRepositoryPool implements SvnRepositoryPool {
  private static final long DEFAULT_IDLE_TIMEOUT = 60*1000;

  private static final int ourMaxCachedDefault = 5;
  private static final int ourMaxConcurrentDefault = 20;
  static final int ourMaxTotal = 100;

  private final int myMaxCached;      // per host
  private int myMaxConcurrent;        // per host
  private final ThrowableConvertor<SVNURL, SVNRepository, SVNException> myCreator;
  private final ThrowableConsumer<Pair<SVNURL, SVNRepository>, SVNException> myAdjuster;
  private final Map<String, RepoGroup> myGroups;
  private ApplicationLevelNumberConnectionsGuard myGuard;

  private long myConnectionTimeout;

  private boolean myDisposed;
  private final Object myLock;

  public CachingSvnRepositoryPool(ThrowableConvertor<SVNURL, SVNRepository, SVNException> creator,
                                  final int maxCached, final int maxConcurrent,
                                  ThrowableConsumer<Pair<SVNURL, SVNRepository>, SVNException> adjuster,
                                  final ApplicationLevelNumberConnectionsGuard guard) {
    myGuard = guard;
    myLock = new Object();
    myConnectionTimeout = DEFAULT_IDLE_TIMEOUT;
    myCreator = creator;
    myAdjuster = adjuster;
    myMaxCached = maxCached > 0 ? maxCached : ourMaxCachedDefault;
    myMaxConcurrent = maxConcurrent > 0 ? maxConcurrent : ourMaxConcurrentDefault;
    if (myMaxConcurrent < myMaxCached) {
      myMaxConcurrent = myMaxCached;
    }
    myGroups = new HashMap<String, RepoGroup>();
    myDisposed = false;
  }

  public CachingSvnRepositoryPool(ThrowableConvertor<SVNURL, SVNRepository, SVNException> creator,
                                  ThrowableConsumer<Pair<SVNURL, SVNRepository>, SVNException> adjuster,
                                  final ApplicationLevelNumberConnectionsGuard guard) {
    this(creator, -1, -1, adjuster, guard);
  }


  public void setConnectionTimeout(long connectionTimeout) {
    synchronized (myLock) {
      myConnectionTimeout = connectionTimeout;
    }
  }

  public void waitingInterrupted() {
    synchronized (myLock) {
      for (RepoGroup group : myGroups.values()) {
        group.interruptWaiting();
      }
    }
  }

  public void check() {
    synchronized (myLock) {
      if (myDisposed) return;
      for (RepoGroup group : myGroups.values()) {
        group.recheck();
      }
    }
  }

  @Override
  public SVNRepository getRepo(SVNURL url, boolean mayReuse) throws SVNException {
    synchronized (myLock) {
      if (myDisposed) throw new ProcessCanceledException();

      final String host = url.getHost();
      RepoGroup group = myGroups.get(host);
      if (group == null) {
        group = new RepoGroup(myCreator, myMaxCached, myMaxConcurrent, myAdjuster, myGuard, myLock, myConnectionTimeout);
      }
      myGroups.put(host, group);
      return group.getRepo(url, mayReuse);
    }
  }

  @Override
  public void returnRepo(SVNRepository repo) {
    synchronized (myLock) {
      if (myDisposed) {
        repo.closeSession();
        myGuard.connectionDestroyed(1);
        return;
      }
      final String host = repo.getLocation().getHost();
      RepoGroup group = myGroups.get(host);
      assert group != null;
      group.returnRepo(repo);
    }
  }

  @Override
  public void dispose() {
    synchronized (myLock) {
      myDisposed = true;
      for (RepoGroup group : myGroups.values()) {
        group.dispose();
      }
    }
  }

  public void closeInactive() {
    synchronized (myLock) {
      for (RepoGroup group : myGroups.values()) {
        group.closeInactive();
      }
    }
  }

  // per host
  public static class RepoGroup implements SvnRepositoryPool {
    private final ThrowableConvertor<SVNURL, SVNRepository, SVNException> myCreator;

    private final int myMaxCached;      // per host
    private final int myMaxConcurrent;        // per host
    private final ThrowableConsumer<Pair<SVNURL, SVNRepository>, SVNException> myAdjuster;
    private final ApplicationLevelNumberConnectionsGuard myGuard;

    private final TreeMap<Long, SVNRepository> myInactive;
    private final Set<SVNRepository> myUsed;
    private boolean myDisposed;
    private final Object myWait;
    private long myConnectionTimeout;

    private RepoGroup(ThrowableConvertor<SVNURL, SVNRepository, SVNException> creator, int cached, int concurrent,
                      final ThrowableConsumer<Pair<SVNURL, SVNRepository>, SVNException> adjuster,
                      final ApplicationLevelNumberConnectionsGuard guard, final Object waitObj, final long connectionTimeout) {
      myCreator = creator;
      myMaxCached = cached;
      myMaxConcurrent = concurrent;
      myAdjuster = adjuster;
      myGuard = guard;
      myConnectionTimeout = connectionTimeout;

      myInactive = new TreeMap<Long, SVNRepository>();
      myUsed = new HashSet<SVNRepository>();

      myDisposed = false;
      myWait = waitObj;
    }

    public void dispose() {
      final List<SVNRepository> listForClose = new ArrayList<SVNRepository>();
      listForClose.addAll(myInactive.values());
      myInactive.clear();
      myUsed.clear();   // todo use counter instead of list??

      synchronized (myWait) {
        myWait.notifyAll();
      }
      myDisposed = true;
      myWait.notifyAll();

      myGuard.connectionDestroyed(listForClose.size());
      ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
        @Override
        public void run() {
          for (SVNRepository repository : listForClose) {
            repository.closeSession();
          }
        }
      });
    }

    public void interruptWaiting() {
      synchronized (myWait) {
        myWait.notifyAll();
      }
    }

    @Override
    public SVNRepository getRepo(SVNURL url, boolean mayReuse) throws SVNException {
      if (myDisposed) return null;
      if (! myInactive.isEmpty() && mayReuse) {
        return fromInactive(url);
      }
      myGuard.waitForTotalNumberOfConnectionsOk();

      if (myUsed.size() >= myMaxConcurrent) {
        synchronized (myWait) {
          if ((myUsed.size() + myInactive.size()) >= myMaxConcurrent) {
            while ((myUsed.size() + myInactive.size()) >= myMaxConcurrent && ! myDisposed) {
              try {
                myWait.wait(300);
              }
              catch (InterruptedException e) {
                //
              }
              ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
              if (indicator != null && indicator.isCanceled()) {
                throw new SVNException(SVNErrorMessage.create(SVNErrorCode.CANCELLED));
              }
            }

            //somewhy unblocked
            if (myDisposed) {
              myWait.notifyAll();    // unblock others
              throw new ProcessCanceledException();
            }
          }
        }
      }
      if (! myInactive.isEmpty() && mayReuse) {
        return fromInactive(url);
      }
      assert myUsed.size() <= myMaxConcurrent;
      final SVNRepository fun = myCreator.convert(url);
      myUsed.add(fun);
      myGuard.connectionCreated();
      return fun;
    }

    private SVNRepository fromInactive(SVNURL url) throws SVNException {
      // oldest
      final Map.Entry<Long, SVNRepository> entry = myInactive.firstEntry();
      final SVNRepository next = entry.getValue();
      myInactive.remove(entry.getKey());
      myAdjuster.consume(Pair.create(url, next));
      if (! myGuard.shouldKeepConnectionLocally()) {
        myInactive.clear();
      }
      return next;
    }

    @Override
    public void returnRepo(SVNRepository repo) {
      myUsed.remove(repo);
      if (myGuard.shouldKeepConnectionLocally() && myInactive.size() < myMaxCached) {
        long time = System.currentTimeMillis();
        if (myInactive.containsKey(time)) {
          time = myInactive.lastKey() + 1;
        }
        myInactive.put(time, repo);
      } else {
        repo.closeSession();
        myGuard.connectionDestroyed(1);
      }
    }

    public void recheck() {
      final long time = System.currentTimeMillis();
      final Set<Long> longs = myInactive.keySet();
      final Iterator<Long> iterator = longs.iterator();
      while (iterator.hasNext()) {
        final Long next = iterator.next();
        if (time - next > myConnectionTimeout) {
          myInactive.get(next).closeSession();
          myGuard.connectionDestroyed(1);
          iterator.remove();
        } else {
          break;
        }
      }
    }

    public int closeInactive() {
      int cnt = myInactive.size();
      for (SVNRepository repository : myInactive.values()) {
        repository.closeSession();
        myGuard.connectionDestroyed(1);
      }
      myInactive.clear();
      return cnt;
    }

    public int getUsedSize() {
      return myUsed.size();
    }

    public int getInactiveSize() {
      return myInactive.size();
    }
  }

  public Map<String, RepoGroup> getGroups() {
    assert ApplicationManager.getApplication().isUnitTestMode();
    return myGroups;
  }
}
