/*
 * 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.utils;

import java.lang.reflect.Type;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitblit.Constants;
import com.gitblit.Constants.FederationProposalResult;
import com.gitblit.Constants.FederationRequest;
import com.gitblit.Constants.FederationToken;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.models.FederationModel;
import com.gitblit.models.FederationProposal;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.google.gson.reflect.TypeToken;

/**
 * Utility methods for federation functions.
 *
 * @author James Moger
 *
 */
public class FederationUtils {

	private static final Type REPOSITORIES_TYPE = new TypeToken<Map<String, RepositoryModel>>() {
	}.getType();

	private static final Type SETTINGS_TYPE = new TypeToken<Map<String, String>>() {
	}.getType();

	private static final Type USERS_TYPE = new TypeToken<Collection<UserModel>>() {
	}.getType();

	private static final Type TEAMS_TYPE = new TypeToken<Collection<TeamModel>>() {
	}.getType();

	private static final Logger LOGGER = LoggerFactory.getLogger(FederationUtils.class);

	/**
	 * Returns an url to this servlet for the specified parameters.
	 *
	 * @param sourceURL
	 *            the url of the source gitblit instance
	 * @param token
	 *            the federation token of the source gitblit instance
	 * @param req
	 *            the pull type request
	 */
	public static String asLink(String sourceURL, String token, FederationRequest req) {
		return asLink(sourceURL, null, token, req, null);
	}

	/**
	 *
	 * @param remoteURL
	 *            the url of the remote gitblit instance
	 * @param tokenType
	 *            the type of federation token of a gitblit instance
	 * @param token
	 *            the federation token of a gitblit instance
	 * @param req
	 *            the pull type request
	 * @param myURL
	 *            the url of this gitblit instance
	 * @return
	 */
	public static String asLink(String remoteURL, FederationToken tokenType, String token,
			FederationRequest req, String myURL) {
		if (remoteURL.length() > 0 && remoteURL.charAt(remoteURL.length() - 1) == '/') {
			remoteURL = remoteURL.substring(0, remoteURL.length() - 1);
		}
		if (req == null) {
			req = FederationRequest.PULL_REPOSITORIES;
		}
		return remoteURL + Constants.FEDERATION_PATH + "?req=" + req.name().toLowerCase()
				+ (token == null ? "" : ("&token=" + token))
				+ (tokenType == null ? "" : ("&tokenType=" + tokenType.name().toLowerCase()))
				+ (myURL == null ? "" : ("&url=" + StringUtils.encodeURL(myURL)));
	}

	/**
	 * Returns the list of federated gitblit instances that this instance will
	 * try to pull.
	 *
	 * @return list of registered gitblit instances
	 */
	public static List<FederationModel> getFederationRegistrations(IStoredSettings settings) {
		List<FederationModel> federationRegistrations = new ArrayList<FederationModel>();
		List<String> keys = settings.getAllKeys(Keys.federation._ROOT);
		keys.remove(Keys.federation.name);
		keys.remove(Keys.federation.passphrase);
		keys.remove(Keys.federation.allowProposals);
		keys.remove(Keys.federation.proposalsFolder);
		keys.remove(Keys.federation.defaultFrequency);
		keys.remove(Keys.federation.sets);
		Collections.sort(keys);
		Map<String, FederationModel> federatedModels = new HashMap<String, FederationModel>();
		for (String key : keys) {
			String value = key.substring(Keys.federation._ROOT.length() + 1);
			List<String> values = StringUtils.getStringsFromValue(value, "\\.");
			String server = values.get(0);
			if (!federatedModels.containsKey(server)) {
				federatedModels.put(server, new FederationModel(server));
			}
			String setting = values.get(1);
			if (setting.equals("url")) {
				// url of the origin Gitblit instance
				federatedModels.get(server).url = settings.getString(key, "");
			} else if (setting.equals("token")) {
				// token for the origin Gitblit instance
				federatedModels.get(server).token = settings.getString(key, "");
			} else if (setting.equals("frequency")) {
				// frequency of the pull operation
				federatedModels.get(server).frequency = settings.getString(key, "");
			} else if (setting.equals("folder")) {
				// destination folder of the pull operation
				federatedModels.get(server).folder = settings.getString(key, "");
			} else if (setting.equals("bare")) {
				// whether pulled repositories should be bare
				federatedModels.get(server).bare = settings.getBoolean(key, true);
			} else if (setting.equals("mirror")) {
				// are the repositories to be true mirrors of the origin
				federatedModels.get(server).mirror = settings.getBoolean(key, true);
			} else if (setting.equals("mergeAccounts")) {
				// merge remote accounts into local accounts
				federatedModels.get(server).mergeAccounts = settings.getBoolean(key, false);
			} else if (setting.equals("sendStatus")) {
				// send a status acknowledgment to source Gitblit instance
				// at end of git pull
				federatedModels.get(server).sendStatus = settings.getBoolean(key, false);
			} else if (setting.equals("notifyOnError")) {
				// notify administrators on federation pull failures
				federatedModels.get(server).notifyOnError = settings.getBoolean(key, false);
			} else if (setting.equals("exclude")) {
				// excluded repositories
				federatedModels.get(server).exclusions = settings.getStrings(key);
			} else if (setting.equals("include")) {
				// included repositories
				federatedModels.get(server).inclusions = settings.getStrings(key);
			}
		}

		// verify that registrations have a url and a token
		for (FederationModel model : federatedModels.values()) {
			if (StringUtils.isEmpty(model.url)) {
				LOGGER.warn(MessageFormat.format(
						"Dropping federation registration {0}. Missing url.", model.name));
				continue;
			}
			if (StringUtils.isEmpty(model.token)) {
				LOGGER.warn(MessageFormat.format(
						"Dropping federation registration {0}. Missing token.", model.name));
				continue;
			}
			// set default frequency if unspecified
			if (StringUtils.isEmpty(model.frequency)) {
				model.frequency = settings.getString(Keys.federation.defaultFrequency, "60 mins");
			}
			federationRegistrations.add(model);
		}
		return federationRegistrations;
	}

	/**
	 * Sends a federation poke to the Gitblit instance at remoteUrl. Pokes are
	 * sent by an pulling Gitblit instance to an origin Gitblit instance as part
	 * of the proposal process. This is to ensure that the pulling Gitblit
	 * instance has an IP route to the origin instance.
	 *
	 * @param remoteUrl
	 *            the remote Gitblit instance to send a federation proposal to
	 * @param proposal
	 *            a complete federation proposal
	 * @return true if there is a route to the remoteUrl
	 */
	public static boolean poke(String remoteUrl) throws Exception {
		String url = asLink(remoteUrl, null, FederationRequest.POKE);
		String json = JsonUtils.toJsonString("POKE");
		int status = JsonUtils.sendJsonString(url, json);
		return status == HttpServletResponse.SC_OK;
	}

	/**
	 * Sends a federation proposal to the Gitblit instance at remoteUrl
	 *
	 * @param remoteUrl
	 *            the remote Gitblit instance to send a federation proposal to
	 * @param proposal
	 *            a complete federation proposal
	 * @return the federation proposal result code
	 */
	public static FederationProposalResult propose(String remoteUrl, FederationProposal proposal)
			throws Exception {
		String url = asLink(remoteUrl, null, FederationRequest.PROPOSAL);
		String json = JsonUtils.toJsonString(proposal);
		int status = JsonUtils.sendJsonString(url, json);
		switch (status) {
		case HttpServletResponse.SC_FORBIDDEN:
			// remote Gitblit Federation disabled
			return FederationProposalResult.FEDERATION_DISABLED;
		case HttpServletResponse.SC_BAD_REQUEST:
			// remote Gitblit did not receive any JSON data
			return FederationProposalResult.MISSING_DATA;
		case HttpServletResponse.SC_METHOD_NOT_ALLOWED:
			// remote Gitblit not accepting proposals
			return FederationProposalResult.NO_PROPOSALS;
		case HttpServletResponse.SC_NOT_ACCEPTABLE:
			// remote Gitblit failed to poke this Gitblit instance
			return FederationProposalResult.NO_POKE;
		case HttpServletResponse.SC_OK:
			// received
			return FederationProposalResult.ACCEPTED;
		default:
			return FederationProposalResult.ERROR;
		}
	}

	/**
	 * Retrieves a map of the repositories at the remote gitblit instance keyed
	 * by the repository clone url.
	 *
	 * @param registration
	 * @param checkExclusions
	 *            should returned repositories remove registration exclusions
	 * @return a map of cloneable repositories
	 * @throws Exception
	 */
	public static Map<String, RepositoryModel> getRepositories(FederationModel registration,
			boolean checkExclusions) throws Exception {
		String url = asLink(registration.url, registration.token,
				FederationRequest.PULL_REPOSITORIES);
		Map<String, RepositoryModel> models = JsonUtils.retrieveJson(url, REPOSITORIES_TYPE);
		if (checkExclusions) {
			Map<String, RepositoryModel> includedModels = new HashMap<String, RepositoryModel>();
			for (Map.Entry<String, RepositoryModel> entry : models.entrySet()) {
				if (registration.isIncluded(entry.getValue())) {
					includedModels.put(entry.getKey(), entry.getValue());
				}
			}
			return includedModels;
		}
		return models;
	}

	/**
	 * Tries to pull the gitblit user accounts from the remote gitblit instance.
	 *
	 * @param registration
	 * @return a collection of UserModel objects
	 * @throws Exception
	 */
	public static List<UserModel> getUsers(FederationModel registration) throws Exception {
		String url = asLink(registration.url, registration.token, FederationRequest.PULL_USERS);
		Collection<UserModel> models = JsonUtils.retrieveJson(url, USERS_TYPE);
		List<UserModel> list = new ArrayList<UserModel>(models);
		return list;
	}

	/**
	 * Tries to pull the gitblit team definitions from the remote gitblit
	 * instance.
	 *
	 * @param registration
	 * @return a collection of TeamModel objects
	 * @throws Exception
	 */
	public static List<TeamModel> getTeams(FederationModel registration) throws Exception {
		String url = asLink(registration.url, registration.token, FederationRequest.PULL_TEAMS);
		Collection<TeamModel> models = JsonUtils.retrieveJson(url, TEAMS_TYPE);
		List<TeamModel> list = new ArrayList<TeamModel>(models);
		return list;
	}

	/**
	 * Tries to pull the gitblit server settings from the remote gitblit
	 * instance.
	 *
	 * @param registration
	 * @return a map of the remote gitblit settings
	 * @throws Exception
	 */
	public static Map<String, String> getSettings(FederationModel registration) throws Exception {
		String url = asLink(registration.url, registration.token, FederationRequest.PULL_SETTINGS);
		Map<String, String> settings = JsonUtils.retrieveJson(url, SETTINGS_TYPE);
		return settings;
	}

	/**
	 * Tries to pull the referenced scripts from the remote gitblit instance.
	 *
	 * @param registration
	 * @return a map of the remote gitblit scripts by script name
	 * @throws Exception
	 */
	public static Map<String, String> getScripts(FederationModel registration) throws Exception {
		String url = asLink(registration.url, registration.token, FederationRequest.PULL_SCRIPTS);
		Map<String, String> scripts = JsonUtils.retrieveJson(url, SETTINGS_TYPE);
		return scripts;
	}

	/**
	 * Send an status acknowledgment to the remote Gitblit server.
	 *
	 * @param identification
	 *            identification of this pulling instance
	 * @param registration
	 *            the source Gitblit instance to receive an acknowledgment
	 * @param results
	 *            the results of your pull operation
	 * @return true, if the remote Gitblit instance acknowledged your results
	 * @throws Exception
	 */
	public static boolean acknowledgeStatus(String identification, FederationModel registration)
			throws Exception {
		String url = asLink(registration.url, null, registration.token, FederationRequest.STATUS,
				identification);
		String json = JsonUtils.toJsonString(registration);
		int status = JsonUtils.sendJsonString(url, json);
		return status == HttpServletResponse.SC_OK;
	}
}
