/*
 * Copyright 2011 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.models;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.gitblit.Constants.FederationPullStatus;
import com.gitblit.utils.StringUtils;

/**
 * Represents a federated server registration. Gitblit federation allows one
 * Gitblit instance to pull the repositories and configuration from another
 * Gitblit instance. This is a backup operation and can be considered something
 * like svn-sync.
 *
 */
public class FederationModel implements Serializable, Comparable<FederationModel> {

	private static final long serialVersionUID = 1L;

	public String name;

	public String url;

	public String token;

	public String frequency;

	public String folder;

	public boolean bare;

    public boolean mirror;

	public boolean mergeAccounts;

	public boolean sendStatus;

	public boolean notifyOnError;

	public List<String> exclusions = new ArrayList<String>();

	public List<String> inclusions = new ArrayList<String>();

	public Date lastPull;

	public Date nextPull;

	private Map<String, FederationPullStatus> results = new ConcurrentHashMap<String, FederationPullStatus>();

	/**
	 * The constructor for a remote server configuration.
	 *
	 * @param serverName
	 */
	public FederationModel(String serverName) {
		this.name = serverName;
		bare = true;
		mirror = true;
		this.lastPull = new Date(0);
		this.nextPull = new Date(0);
	}

	public boolean isIncluded(RepositoryModel repository) {
		// if exclusions has the all wildcard, then check for specific
		// inclusions
		if (exclusions.contains("*")) {
			for (String name : inclusions) {
				if (StringUtils.fuzzyMatch(repository.name, name)) {
					results.put(repository.name, FederationPullStatus.PENDING);
					return true;
				}
			}
			results.put(repository.name, FederationPullStatus.EXCLUDED);
			return false;
		}

		// named exclusions
		for (String name : exclusions) {
			if (StringUtils.fuzzyMatch(repository.name, name)) {
				results.put(repository.name, FederationPullStatus.EXCLUDED);
				return false;
			}
		}

		// included by default
		results.put(repository.name, FederationPullStatus.PENDING);
		return true;
	}

	/**
	 * Updates the pull status of a particular repository in this federation
	 * registration.
	 *
	 * @param repository
	 * @param status
	 */
	public void updateStatus(RepositoryModel repository, FederationPullStatus status) {
		if (!results.containsKey(repository.name)) {
			results.put(repository.name, FederationPullStatus.PENDING);
		}
		if (status != null) {
			results.put(repository.name, status);
		}
	}

	public List<RepositoryStatus> getStatusList() {
		List<RepositoryStatus> list = new ArrayList<RepositoryStatus>();
		for (Map.Entry<String, FederationPullStatus> entry : results.entrySet()) {
			list.add(new RepositoryStatus(entry.getKey(), entry.getValue()));
		}
		return list;
	}

	/**
	 * Iterates over the current pull results and returns the lowest pull
	 * status.
	 *
	 * @return the lowest pull status of the registration
	 */
	public FederationPullStatus getLowestStatus() {
		if (results.size() == 0) {
			return FederationPullStatus.PENDING;
		}
		FederationPullStatus status = FederationPullStatus.MIRRORED;
		for (FederationPullStatus result : results.values()) {
			if (result.ordinal() < status.ordinal()) {
				status = result;
			}
		}
		return status;
	}

	/**
	 * Returns true if this registration represents the result data sent by a
	 * pulling Gitblit instance.
	 *
	 * @return true, if this is result data
	 */
	public boolean isResultData() {
		return !url.toLowerCase().startsWith("http://") && !url.toLowerCase().startsWith("https://");
	}

	@Override
	public String toString() {
		return "Federated " + name + " (" + url + ")";
	}

	@Override
	public int compareTo(FederationModel o) {
		boolean r1 = isResultData();
		boolean r2 = o.isResultData();
		if ((r1 && r2) || (!r1 && !r2)) {
			// sort registrations and results by name
			return name.compareTo(o.name);
		}
		// sort registrations first
		if (r1) {
			return 1;
		}
		return -1;
	}

	/**
	 * Class that encapsulates a point-in-time pull result.
	 *
	 */
	public static class RepositoryStatus implements Serializable, Comparable<RepositoryStatus> {

		private static final long serialVersionUID = 1L;

		public final String name;
		public final FederationPullStatus status;

		RepositoryStatus(String name, FederationPullStatus status) {
			this.name = name;
			this.status = status;
		}

		@Override
		public int compareTo(RepositoryStatus o) {
			if (status.equals(o.status)) {
				return StringUtils.compareRepositoryNames(name, o.name);
			}
			return status.compareTo(o.status);
		}
	}
}
