/*
 * 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.servlet;

import java.io.File;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import javax.servlet.http.HttpServletResponse;

import com.gitblit.Constants.FederationRequest;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.manager.IFederationManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IUserManager;
import com.gitblit.models.FederationModel;
import com.gitblit.models.FederationProposal;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.FederationUtils;
import com.gitblit.utils.FileUtils;
import com.gitblit.utils.HttpUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.utils.TimeUtils;

/**
 * Handles federation requests.
 *
 * @author James Moger
 *
 */
@Singleton
public class FederationServlet extends JsonServlet {

	private static final long serialVersionUID = 1L;

	private IStoredSettings settings;

	private IUserManager userManager;

	private IRepositoryManager repositoryManager;

	private IFederationManager federationManager;

	@Inject
	public FederationServlet(
			IStoredSettings settings,
			IUserManager userManager,
			IRepositoryManager repositoryManager,
			IFederationManager federationManager) {

		this.settings = settings;
		this.userManager = userManager;
		this.repositoryManager = repositoryManager;
		this.federationManager = federationManager;
	}

	/**
	 * Processes a federation request.
	 *
	 * @param request
	 * @param response
	 * @throws javax.servlet.ServletException
	 * @throws java.io.IOException
	 */

	@Override
	protected void processRequest(javax.servlet.http.HttpServletRequest request,
			javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
			java.io.IOException {

		FederationRequest reqType = FederationRequest.fromName(request.getParameter("req"));
		logger.info(MessageFormat.format("Federation {0} request from {1}", reqType,
				request.getRemoteAddr()));

		if (FederationRequest.POKE.equals(reqType)) {
			// Gitblit always responds to POKE requests to verify a connection
			logger.info("Received federation POKE from " + request.getRemoteAddr());
			return;
		}

		if (!settings.getBoolean(Keys.git.enableGitServlet, true)) {
			logger.warn(Keys.git.enableGitServlet + " must be set TRUE for federation requests.");
			response.sendError(HttpServletResponse.SC_FORBIDDEN);
			return;
		}

		String uuid = settings.getString(Keys.federation.passphrase, "");
		if (StringUtils.isEmpty(uuid)) {
			logger.warn(Keys.federation.passphrase
					+ " is not properly set!  Federation request denied.");
			response.sendError(HttpServletResponse.SC_FORBIDDEN);
			return;
		}

		if (FederationRequest.PROPOSAL.equals(reqType)) {
			// Receive a gitblit federation proposal
			FederationProposal proposal = deserialize(request, response, FederationProposal.class);
			if (proposal == null) {
				return;
			}

			// reject proposal, if not receipt prohibited
			if (!settings.getBoolean(Keys.federation.allowProposals, false)) {
				logger.error(MessageFormat.format("Rejected {0} federation proposal from {1}",
						proposal.tokenType.name(), proposal.url));
				response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
				return;
			}

			// poke the origin Gitblit instance that is proposing federation
			boolean poked = false;
			try {
				poked = FederationUtils.poke(proposal.url);
			} catch (Exception e) {
				logger.error("Failed to poke origin", e);
			}
			if (!poked) {
				logger.error(MessageFormat.format("Failed to send federation poke to {0}",
						proposal.url));
				response.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
				return;
			}

			String gitblitUrl = settings.getString(Keys.web.canonicalUrl, null);
			if (StringUtils.isEmpty(gitblitUrl)) {
				gitblitUrl = HttpUtils.getGitblitURL(request);
			}
			federationManager.submitFederationProposal(proposal, gitblitUrl);
			logger.info(MessageFormat.format(
					"Submitted {0} federation proposal to pull {1} repositories from {2}",
					proposal.tokenType.name(), proposal.repositories.size(), proposal.url));
			response.setStatus(HttpServletResponse.SC_OK);
			return;
		}

		if (FederationRequest.STATUS.equals(reqType)) {
			// Receive a gitblit federation status acknowledgment
			String remoteId = StringUtils.decodeFromHtml(request.getParameter("url"));
			String identification = MessageFormat.format("{0} ({1})", remoteId,
					request.getRemoteAddr());

			// deserialize the status data
			FederationModel results = deserialize(request, response, FederationModel.class);
			if (results == null) {
				return;
			}

			// setup the last and netx pull dates
			results.lastPull = new Date();
			int mins = TimeUtils.convertFrequencyToMinutes(results.frequency, 5);
			results.nextPull = new Date(System.currentTimeMillis() + (mins * 60 * 1000L));

			// acknowledge the receipt of status
			federationManager.acknowledgeFederationStatus(identification, results);
			logger.info(MessageFormat.format(
					"Received status of {0} federated repositories from {1}", results
							.getStatusList().size(), identification));
			response.setStatus(HttpServletResponse.SC_OK);
			return;
		}

		// Determine the federation tokens for this gitblit instance
		String token = request.getParameter("token");
		List<String> tokens = federationManager.getFederationTokens();
		if (!tokens.contains(token)) {
			logger.warn(MessageFormat.format(
					"Received Federation token ''{0}'' does not match the server tokens", token));
			response.sendError(HttpServletResponse.SC_FORBIDDEN);
			return;
		}

		Object result = null;
		if (FederationRequest.PULL_REPOSITORIES.equals(reqType)) {
			String gitblitUrl = settings.getString(Keys.web.canonicalUrl, null);
			if (StringUtils.isEmpty(gitblitUrl)) {
				gitblitUrl = HttpUtils.getGitblitURL(request);
			}
			result = federationManager.getRepositories(gitblitUrl, token);
		} else {
			if (FederationRequest.PULL_SETTINGS.equals(reqType)) {
				// pull settings
				if (!federationManager.validateFederationRequest(reqType, token)) {
					// invalid token to pull users or settings
					logger.warn(MessageFormat.format(
							"Federation token from {0} not authorized to pull SETTINGS",
							request.getRemoteAddr()));
					response.sendError(HttpServletResponse.SC_FORBIDDEN);
					return;
				}
				Map<String, String> map = new HashMap<String, String>();
				List<String> keys = settings.getAllKeys(null);
				for (String key : keys) {
					map.put(key, settings.getString(key, ""));
				}
				result = map;
			} else if (FederationRequest.PULL_USERS.equals(reqType)) {
				// pull users
				if (!federationManager.validateFederationRequest(reqType, token)) {
					// invalid token to pull users or settings
					logger.warn(MessageFormat.format(
							"Federation token from {0} not authorized to pull USERS",
							request.getRemoteAddr()));
					response.sendError(HttpServletResponse.SC_FORBIDDEN);
					return;
				}
				List<String> usernames = userManager.getAllUsernames();
				List<UserModel> users = new ArrayList<UserModel>();
				for (String username : usernames) {
					UserModel user = userManager.getUserModel(username);
					if (!user.excludeFromFederation) {
						users.add(user);
					}
				}
				result = users;
			} else if (FederationRequest.PULL_TEAMS.equals(reqType)) {
				// pull teams
				if (!federationManager.validateFederationRequest(reqType, token)) {
					// invalid token to pull teams
					logger.warn(MessageFormat.format(
							"Federation token from {0} not authorized to pull TEAMS",
							request.getRemoteAddr()));
					response.sendError(HttpServletResponse.SC_FORBIDDEN);
					return;
				}
				List<String> teamnames = userManager.getAllTeamNames();
				List<TeamModel> teams = new ArrayList<TeamModel>();
				for (String teamname : teamnames) {
					TeamModel user = userManager.getTeamModel(teamname);
					teams.add(user);
				}
				result = teams;
			} else if (FederationRequest.PULL_SCRIPTS.equals(reqType)) {
				// pull scripts
				if (!federationManager.validateFederationRequest(reqType, token)) {
					// invalid token to pull script
					logger.warn(MessageFormat.format(
							"Federation token from {0} not authorized to pull SCRIPTS",
							request.getRemoteAddr()));
					response.sendError(HttpServletResponse.SC_FORBIDDEN);
					return;
				}
				Map<String, String> scripts = new HashMap<String, String>();

				Set<String> names = new HashSet<String>();
				names.addAll(settings.getStrings(Keys.groovy.preReceiveScripts));
				names.addAll(settings.getStrings(Keys.groovy.postReceiveScripts));
				for (TeamModel team :  userManager.getAllTeams()) {
					names.addAll(team.preReceiveScripts);
					names.addAll(team.postReceiveScripts);
				}
				File scriptsFolder = repositoryManager.getHooksFolder();
				for (String name : names) {
					File file = new File(scriptsFolder, name);
					if (!file.exists() && !file.getName().endsWith(".groovy")) {
						file = new File(scriptsFolder, name + ".groovy");
					}
					if (file.exists()) {
						// read the script
						String content = FileUtils.readContent(file, "\n");
						scripts.put(name, content);
					} else {
						// missing script?!
						logger.warn(MessageFormat.format("Failed to find push script \"{0}\"", name));
					}
				}
				result = scripts;
			}
		}

		// send the result of the request
		serialize(response, result);
	}
}
