/*
 * Copyright 2013 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.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.transport.FetchResult;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.eclipse.jgit.transport.ReceiveCommand.Type;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.TrackingRefUpdate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.git.ReceiveCommandEvent;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.tickets.BranchTicketService;
import com.gitblit.utils.JGitUtils;

/**
 * The Mirror service handles periodic fetching of mirrored repositories.
 *
 * @author James Moger
 *
 */
public class MirrorService implements Runnable {

	private final Logger logger = LoggerFactory.getLogger(MirrorService.class);

	private final Set<String> repairAttempted = Collections.synchronizedSet(new HashSet<String>());

	private final IStoredSettings settings;

	private final IRepositoryManager repositoryManager;

	private AtomicBoolean running = new AtomicBoolean(false);

	private AtomicBoolean forceClose = new AtomicBoolean(false);

	private final UserModel gitblitUser;

	public MirrorService(
			IStoredSettings settings,
			IRepositoryManager repositoryManager) {

		this.settings = settings;
		this.repositoryManager = repositoryManager;
		this.gitblitUser = new UserModel("gitblit");
		this.gitblitUser.displayName = "Gitblit";
	}

	public boolean isReady() {
		return settings.getBoolean(Keys.git.enableMirroring, false);
	}

	public boolean isRunning() {
		return running.get();
	}

	public void close() {
		forceClose.set(true);
	}

	@Override
	public void run() {
		if (!isReady()) {
			return;
		}

		running.set(true);

		for (String repositoryName : repositoryManager.getRepositoryList()) {
			if (forceClose.get()) {
				break;
			}
			if (repositoryManager.isCollectingGarbage(repositoryName)) {
				logger.debug("mirror is skipping {} garbagecollection", repositoryName);
				continue;
			}
			RepositoryModel model = null;
			Repository repository = null;
			try {
				model = repositoryManager.getRepositoryModel(repositoryName);
				if (!model.isMirror && !model.isBare) {
					// repository must be a valid bare git mirror
					logger.debug("mirror is skipping {} !mirror !bare", repositoryName);
					continue;
				}

				repository = repositoryManager.getRepository(repositoryName);
				if (repository == null) {
					logger.warn(MessageFormat.format("MirrorExecutor is missing repository {0}?!?", repositoryName));
					continue;
				}

				// automatically repair (some) invalid fetch ref specs
				if (!repairAttempted.contains(repositoryName)) {
					repairAttempted.add(repositoryName);
					JGitUtils.repairFetchSpecs(repository);
				}

				// find the first mirror remote - there should only be one
				StoredConfig rc = repository.getConfig();
				RemoteConfig mirror = null;
				List<RemoteConfig> configs = RemoteConfig.getAllRemoteConfigs(rc);
				for (RemoteConfig config : configs) {
					if (config.isMirror()) {
						mirror = config;
						break;
					}
				}

				if (mirror == null) {
					// repository does not have a mirror remote
					logger.debug("mirror is skipping {} no mirror remote found", repositoryName);
					continue;
				}

				logger.debug("checking {} remote {} for ref updates", repositoryName, mirror.getName());
				final boolean testing = false;
				Git git = new Git(repository);
				FetchResult result = git.fetch().setRemote(mirror.getName()).setDryRun(testing).call();
				Collection<TrackingRefUpdate> refUpdates = result.getTrackingRefUpdates();
				if (refUpdates.size() > 0) {
					ReceiveCommand ticketBranchCmd = null;
					for (TrackingRefUpdate ru : refUpdates) {
						StringBuilder sb = new StringBuilder();
						sb.append("updated mirror ");
						sb.append(repositoryName);
						sb.append(" ");
						sb.append(ru.getRemoteName());
						sb.append(" -> ");
						sb.append(ru.getLocalName());
						if (ru.getResult() == Result.FORCED) {
							sb.append(" (forced)");
						}
						sb.append(" ");
						sb.append(ru.getOldObjectId() == null ? "" : ru.getOldObjectId().abbreviate(7).name());
						sb.append("..");
						sb.append(ru.getNewObjectId() == null ? "" : ru.getNewObjectId().abbreviate(7).name());
						logger.info(sb.toString());

						if (BranchTicketService.BRANCH.equals(ru.getLocalName())) {
							ReceiveCommand.Type type = null;
							switch (ru.getResult()) {
							case NEW:
								type = Type.CREATE;
								break;
							case FAST_FORWARD:
								type = Type.UPDATE;
								break;
							case FORCED:
								type = Type.UPDATE_NONFASTFORWARD;
								break;
							default:
								type = null;
								break;
							}

							if (type != null) {
								ticketBranchCmd = new ReceiveCommand(ru.getOldObjectId(),
									ru.getNewObjectId(), ru.getLocalName(), type);
							}
						}
					}

					if (ticketBranchCmd != null) {
						repository.fireEvent(new ReceiveCommandEvent(model, ticketBranchCmd));
					}
				}
			} catch (Exception e) {
				logger.error("Error updating mirror " + repositoryName, e);
			} finally {
				// cleanup
				if (repository != null) {
					repository.close();
				}
			}
		}

		running.set(false);
	}
}
