/*
 * Copyright 2012 gitblit.com.
 *
 * 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.gitblit.service;

import java.text.MessageFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

import org.eclipse.jgit.api.GarbageCollectCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.Repository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.models.RepositoryModel;
import com.gitblit.utils.FileUtils;

/**
 * The Garbage Collector Service handles periodic garbage collection in repositories.
 *
 * @author James Moger
 *
 */
public class GarbageCollectorService implements Runnable {

	public static enum GCStatus {
		READY, COLLECTING;

		public boolean exceeds(GCStatus s) {
			return ordinal() > s.ordinal();
		}
	}
	private final Logger logger = LoggerFactory.getLogger(GarbageCollectorService.class);

	private final IStoredSettings settings;

	private final IRepositoryManager repositoryManager;

	private AtomicBoolean running = new AtomicBoolean(false);

	private AtomicBoolean forceClose = new AtomicBoolean(false);

	private final Map<String, GCStatus> gcCache = new ConcurrentHashMap<String, GCStatus>();

	public GarbageCollectorService(
			IStoredSettings settings,
			IRepositoryManager repositoryManager) {

		this.settings = settings;
		this.repositoryManager = repositoryManager;
	}

	/**
	 * Indicates if the GC executor is ready to process repositories.
	 *
	 * @return true if the GC executor is ready to process repositories
	 */
	public boolean isReady() {
		return settings.getBoolean(Keys.git.enableGarbageCollection, false);
	}

	public boolean isRunning() {
		return running.get();
	}

	public boolean lock(String repositoryName) {
		return setGCStatus(repositoryName, GCStatus.COLLECTING);
	}

	/**
	 * Tries to set a GCStatus for the specified repository.
	 *
	 * @param repositoryName
	 * @return true if the status has been set
	 */
	private boolean setGCStatus(String repositoryName, GCStatus status) {
		String key = repositoryName.toLowerCase();
		if (gcCache.containsKey(key)) {
			if (gcCache.get(key).exceeds(GCStatus.READY)) {
				// already collecting or blocked
				return false;
			}
		}
		gcCache.put(key, status);
		return true;
	}

	/**
	 * Returns true if Gitblit is actively collecting garbage in this repository.
	 *
	 * @param repositoryName
	 * @return true if actively collecting garbage
	 */
	public boolean isCollectingGarbage(String repositoryName) {
		String key = repositoryName.toLowerCase();
		return gcCache.containsKey(key) && GCStatus.COLLECTING.equals(gcCache.get(key));
	}

	/**
	 * Resets the GC status to ready.
	 *
	 * @param repositoryName
	 */
	public void releaseLock(String repositoryName) {
		gcCache.put(repositoryName.toLowerCase(), GCStatus.READY);
	}

	public void close() {
		forceClose.set(true);
	}

	@Override
	public void run() {
		if (!isReady()) {
			return;
		}

		running.set(true);
		Date now = new Date();

		for (String repositoryName : repositoryManager.getRepositoryList()) {
			if (forceClose.get()) {
				break;
			}
			if (isCollectingGarbage(repositoryName)) {
				logger.warn(MessageFormat.format("Already collecting garbage from {0}?!?", repositoryName));
				continue;
			}
			boolean garbageCollected = false;
			RepositoryModel model = null;
			Repository repository = null;
			try {
				model = repositoryManager.getRepositoryModel(repositoryName);
				repository = repositoryManager.getRepository(repositoryName);
				if (repository == null) {
					logger.warn(MessageFormat.format("GCExecutor is missing repository {0}?!?", repositoryName));
					continue;
				}

				if (!repositoryManager.isIdle(repository)) {
					logger.debug(MessageFormat.format("GCExecutor is skipping {0} because it is not idle", repositoryName));
					continue;
				}

				// By setting the GCStatus to COLLECTING we are
				// disabling *all* access to this repository from Gitblit.
				// Think of this as a clutch in a manual transmission vehicle.
				if (!setGCStatus(repositoryName, GCStatus.COLLECTING)) {
					logger.warn(MessageFormat.format("Can not acquire GC lock for {0}, skipping", repositoryName));
					continue;
				}

				logger.debug(MessageFormat.format("GCExecutor locked idle repository {0}", repositoryName));

				Git git = new Git(repository);
				GarbageCollectCommand gc = git.gc();
				Properties stats = gc.getStatistics();

				// determine if this is a scheduled GC
				Calendar cal = Calendar.getInstance();
				cal.setTime(model.lastGC);
				cal.set(Calendar.HOUR_OF_DAY, 0);
				cal.set(Calendar.MINUTE, 0);
				cal.set(Calendar.SECOND, 0);
				cal.set(Calendar.MILLISECOND, 0);
				cal.add(Calendar.DATE, model.gcPeriod);
				Date gcDate = cal.getTime();
				boolean shouldCollectGarbage = now.after(gcDate);

				// determine if filesize triggered GC
				long gcThreshold = FileUtils.convertSizeToLong(model.gcThreshold, 500*1024L);
				long sizeOfLooseObjects = (Long) stats.get("sizeOfLooseObjects");
				boolean hasEnoughGarbage = sizeOfLooseObjects >= gcThreshold;

				// if we satisfy one of the requirements, GC
				boolean hasGarbage = sizeOfLooseObjects > 0;
				if (hasGarbage && (hasEnoughGarbage || shouldCollectGarbage)) {
					long looseKB = sizeOfLooseObjects/1024L;
					logger.info(MessageFormat.format("Collecting {1} KB of loose objects from {0}", repositoryName, looseKB));

					// do the deed
					gc.call();

					garbageCollected = true;
				}
			} catch (Exception e) {
				logger.error("Error collecting garbage in " + repositoryName, e);
			} finally {
				// cleanup
				if (repository != null) {
					if (garbageCollected) {
						// update the last GC date
						model.lastGC = new Date();
						repositoryManager.updateConfiguration(repository, model);
					}

					repository.close();
				}

				// reset the GC lock
				releaseLock(repositoryName);
				logger.debug(MessageFormat.format("GCExecutor released GC lock for {0}", repositoryName));
			}
		}

		running.set(false);
	}
}
