/*
 * 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.wicket.panels;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.wicket.Component;
import org.apache.wicket.RequestCycle;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.image.ContextImage;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.markup.repeater.data.ListDataProvider;
import org.apache.wicket.protocol.http.WebRequest;
import org.apache.wicket.protocol.http.request.WebClientInfo;

import com.gitblit.Constants.AccessPermission;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Keys;
import com.gitblit.models.GitClientApplication;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.RepositoryUrl;
import com.gitblit.models.UserModel;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.ExternalImage;
import com.gitblit.wicket.GitBlitWebSession;
import com.gitblit.wicket.WicketUtils;

/**
 * Smart repository url panel which can display multiple Gitblit repository urls
 * and also supports 3rd party app clone links.
 *
 * @author James Moger
 *
 */
public class RepositoryUrlPanel extends BasePanel {

	private static final long serialVersionUID = 1L;

	private final String externalPermission = "?";

	private boolean onlyUrls;
	private UserModel user;
	private RepositoryModel repository;
	private RepositoryUrl primaryUrl;
	private Map<String, String> urlPermissionsMap;
	private Map<AccessRestrictionType, String> accessRestrictionsMap;

	public RepositoryUrlPanel(String wicketId, boolean onlyUrls, UserModel user, RepositoryModel repository) {
		super(wicketId);
		this.onlyUrls = onlyUrls;
		this.user = user == null ? UserModel.ANONYMOUS : user;
		this.repository = repository;
		this.urlPermissionsMap = new HashMap<String, String>();
	}

	@Override
	protected void onInitialize() {
		super.onInitialize();

		HttpServletRequest req = ((WebRequest) getRequest()).getHttpServletRequest();

		List<RepositoryUrl> repositoryUrls = app().services().getRepositoryUrls(req, user, repository);
		// grab primary url from the top of the list
		primaryUrl = repositoryUrls.size() == 0 ? null : repositoryUrls.get(0);

		boolean canClone = primaryUrl != null && (!primaryUrl.hasPermission() || primaryUrl.permission.atLeast(AccessPermission.CLONE));

		if (repositoryUrls.size() == 0 || !canClone) {
			// no urls, nothing to show.
			add(new Label("repositoryUrlPanel").setVisible(false));
			add(new Label("applicationMenusPanel").setVisible(false));
			add(new Label("repositoryIndicators").setVisible(false));
			return;
		}

		// display primary url
		add(createPrimaryUrlPanel("repositoryUrlPanel", repository, repositoryUrls));

		if (onlyUrls) {
			add(new Label("repositoryIndicators").setVisible(false));
		} else {
			add(createRepositoryIndicators(repository));
		}

		boolean allowAppLinks = app().settings().getBoolean(Keys.web.allowAppCloneLinks, true);
		if (onlyUrls || !canClone || !allowAppLinks) {
			// only display the url(s)
			add(new Label("applicationMenusPanel").setVisible(false));
			return;
		}
		// create the git client application menus
		add(createApplicationMenus("applicationMenusPanel", user, repository, repositoryUrls));
	}

	public String getPrimaryUrl() {
		return primaryUrl == null ? "" : primaryUrl.url;
	}

	protected Fragment createPrimaryUrlPanel(String wicketId, final RepositoryModel repository, List<RepositoryUrl> repositoryUrls) {

		Fragment urlPanel = new Fragment(wicketId, "repositoryUrlFragment", this);
		urlPanel.setRenderBodyOnly(true);

		if (repositoryUrls.size() == 1) {
			//
			// Single repository url, no dropdown menu
			//
			urlPanel.add(new Label("menu").setVisible(false));
		} else {
			//
			// Multiple repository urls, show url drop down menu
			//
			ListDataProvider<RepositoryUrl> urlsDp = new ListDataProvider<RepositoryUrl>(repositoryUrls);
			DataView<RepositoryUrl> repoUrlMenuItems = new DataView<RepositoryUrl>("repoUrls", urlsDp) {
				private static final long serialVersionUID = 1L;

				@Override
				public void populateItem(final Item<RepositoryUrl> item) {
					RepositoryUrl repoUrl = item.getModelObject();
					// repository url
					Fragment fragment = new Fragment("repoUrl", "actionFragment", this);
					Component content = new Label("content", repoUrl.url).setRenderBodyOnly(true);
					WicketUtils.setCssClass(content, "commandMenuItem");
					fragment.add(content);
					item.add(fragment);

					Label permissionLabel = new Label("permission", repoUrl.hasPermission() ? repoUrl.permission.toString() : externalPermission);
					WicketUtils.setPermissionClass(permissionLabel, repoUrl.permission);
					String tooltip = getProtocolPermissionDescription(repository, repoUrl);
					WicketUtils.setHtmlTooltip(permissionLabel, tooltip);
					fragment.add(permissionLabel);
					fragment.add(createCopyFragment(repoUrl.url));
				}
			};

			Fragment urlMenuFragment = new Fragment("menu", "urlProtocolMenuFragment", this);
			urlMenuFragment.setRenderBodyOnly(true);
			urlMenuFragment.add(new Label("menuText", getString("gb.url")));
			urlMenuFragment.add(repoUrlMenuItems);
			urlPanel.add(urlMenuFragment);
		}

		// access restriction icon and tooltip
		if (repository.isMirror) {
			urlPanel.add(WicketUtils.newImage("accessRestrictionIcon", "mirror_16x16.png",
					getString("gb.isMirror")));
		} else if (app().services().isServingRepositories()) {
			switch (repository.accessRestriction) {
			case NONE:
				urlPanel.add(WicketUtils.newClearPixel("accessRestrictionIcon").setVisible(false));
				break;
			case PUSH:
				urlPanel.add(WicketUtils.newImage("accessRestrictionIcon", "lock_go_16x16.png",
						getAccessRestrictions().get(repository.accessRestriction)));
				break;
			case CLONE:
				urlPanel.add(WicketUtils.newImage("accessRestrictionIcon", "lock_pull_16x16.png",
						getAccessRestrictions().get(repository.accessRestriction)));
				break;
			case VIEW:
				urlPanel.add(WicketUtils.newImage("accessRestrictionIcon", "shield_16x16.png",
						getAccessRestrictions().get(repository.accessRestriction)));
				break;
			default:
				if (repositoryUrls.size() == 1) {
					// force left end cap to have some width
					urlPanel.add(WicketUtils.newBlankIcon("accessRestrictionIcon"));
				} else {
					urlPanel.add(WicketUtils.newClearPixel("accessRestrictionIcon").setVisible(false));
				}
			}
		} else {
			if (repositoryUrls.size() == 1) {
				// force left end cap to have some width
				urlPanel.add(WicketUtils.newBlankIcon("accessRestrictionIcon"));
			} else {
				urlPanel.add(WicketUtils.newClearPixel("accessRestrictionIcon").setVisible(false));
			}
		}

		urlPanel.add(new Label("primaryUrl", primaryUrl.url).setRenderBodyOnly(true));

		Label permissionLabel = new Label("primaryUrlPermission", primaryUrl.hasPermission() ? primaryUrl.permission.toString() : externalPermission);
		String tooltip = getProtocolPermissionDescription(repository, primaryUrl);
		WicketUtils.setHtmlTooltip(permissionLabel, tooltip);
		urlPanel.add(permissionLabel);
		urlPanel.add(createCopyFragment(primaryUrl.url));

		return urlPanel;
	}

	protected Fragment createApplicationMenus(String wicketId, final UserModel user, final RepositoryModel repository, final List<RepositoryUrl> repositoryUrls) {
		final List<GitClientApplication> displayedApps = new ArrayList<GitClientApplication>();
		final String userAgent = ((WebClientInfo) GitBlitWebSession.get().getClientInfo()).getUserAgent();

		if (user.canClone(repository)) {
			for (GitClientApplication app : app().gitblit().getClientApplications()) {
				if (app.isActive && app.allowsPlatform(userAgent)) {
					displayedApps.add(app);
				}
			}
		}

		final String baseURL = WicketUtils.getGitblitURL(RequestCycle.get().getRequest());
		ListDataProvider<GitClientApplication> displayedAppsDp = new ListDataProvider<GitClientApplication>(displayedApps);
		DataView<GitClientApplication> appMenus = new DataView<GitClientApplication>("appMenus", displayedAppsDp) {
			private static final long serialVersionUID = 1L;

			@Override
			public void populateItem(final Item<GitClientApplication> item) {
				final GitClientApplication clientApp = item.getModelObject();

				// filter the urls for the client app
				List<RepositoryUrl> urls = new ArrayList<RepositoryUrl>();
				for (RepositoryUrl repoUrl : repositoryUrls) {
					if (clientApp.minimumPermission == null || !repoUrl.hasPermission()) {
						// no minimum permission or untracked permissions, assume it is satisfactory
						if (clientApp.supportsTransport(repoUrl.url)) {
							urls.add(repoUrl);
						}
					} else if (repoUrl.permission.atLeast(clientApp.minimumPermission)) {
						// repo url meets minimum permission requirement
						if (clientApp.supportsTransport(repoUrl.url)) {
							urls.add(repoUrl);
						}
					}
				}

				if (urls.size() == 0) {
					// do not show this app menu because there are no urls
					item.add(new Label("appMenu").setVisible(false));
					return;
				}

				Fragment appMenu = new Fragment("appMenu", "appMenuFragment", this);
				appMenu.setRenderBodyOnly(true);
				item.add(appMenu);

				// menu button
				appMenu.add(new Label("applicationName", clientApp.name));

				// application icon
				Component img;
				if (StringUtils.isEmpty(clientApp.icon)) {
					img = WicketUtils.newClearPixel("applicationIcon").setVisible(false);
				} else {
					if (clientApp.icon.contains("://")) {
						// external image
						img = new ExternalImage("applicationIcon", clientApp.icon);
					} else {
						// context image
						img = WicketUtils.newImage("applicationIcon", clientApp.icon);
					}
				}
				appMenu.add(img);

				// application menu title, may be a link
				if (StringUtils.isEmpty(clientApp.productUrl)) {
					appMenu.add(new Label("applicationTitle", clientApp.toString()));
				} else {
					appMenu.add(new LinkPanel("applicationTitle", null, clientApp.toString(), clientApp.productUrl, true));
				}

				// brief application description
				if (StringUtils.isEmpty(clientApp.description)) {
					appMenu.add(new Label("applicationDescription").setVisible(false));
				} else {
					appMenu.add(new Label("applicationDescription", clientApp.description));
				}

				// brief application legal info, copyright, license, etc
				if (StringUtils.isEmpty(clientApp.legal)) {
					appMenu.add(new Label("applicationLegal").setVisible(false));
				} else {
					appMenu.add(new Label("applicationLegal", clientApp.legal));
				}

				// a nested repeater for all action items
				ListDataProvider<RepositoryUrl> urlsDp = new ListDataProvider<RepositoryUrl>(urls);
				DataView<RepositoryUrl> actionItems = new DataView<RepositoryUrl>("actionItems", urlsDp) {
					private static final long serialVersionUID = 1L;

					@Override
					public void populateItem(final Item<RepositoryUrl> repoLinkItem) {
						RepositoryUrl repoUrl = repoLinkItem.getModelObject();
						Fragment fragment = new Fragment("actionItem", "actionFragment", this);
						fragment.add(createPermissionBadge("permission", repoUrl));

						if (!StringUtils.isEmpty(clientApp.cloneUrl)) {
							// custom registered url
							String url = substitute(clientApp.cloneUrl, repoUrl.url, baseURL, user.username, repository.name);
							fragment.add(new LinkPanel("content", "applicationMenuItem", getString("gb.clone") + " " + repoUrl.url, url));
							repoLinkItem.add(fragment);
							fragment.add(new Label("copyFunction").setVisible(false));
						} else if (!StringUtils.isEmpty(clientApp.command)) {
							// command-line
							String command = substitute(clientApp.command, repoUrl.url, baseURL, user.username, repository.name);
							Label content = new Label("content", command);
							WicketUtils.setCssClass(content, "commandMenuItem");
							fragment.add(content);
							repoLinkItem.add(fragment);

							// copy function for command
							fragment.add(createCopyFragment(command));
						}
					}};
					appMenu.add(actionItems);
			}
		};

		Fragment applicationMenus = new Fragment(wicketId, "applicationMenusFragment", this);
		applicationMenus.add(appMenus);
		return applicationMenus;
	}

	protected String substitute(String pattern, String repoUrl, String baseUrl, String username, String repository) {
		return pattern.replace("${repoUrl}", repoUrl).replace("${baseUrl}", baseUrl).replace("${username}", username).replace("${repository}", repository);
	}

	protected Label createPermissionBadge(String wicketId, RepositoryUrl repoUrl) {
		Label permissionLabel = new Label(wicketId, repoUrl.hasPermission() ? repoUrl.permission.toString() : externalPermission);
		WicketUtils.setPermissionClass(permissionLabel, repoUrl.permission);
		String tooltip = getProtocolPermissionDescription(repository, repoUrl);
		WicketUtils.setHtmlTooltip(permissionLabel, tooltip);
		return permissionLabel;
	}

	protected Fragment createCopyFragment(String text) {
		if (app().settings().getBoolean(Keys.web.allowFlashCopyToClipboard, true)) {
			// clippy: flash-based copy & paste
			Fragment copyFragment = new Fragment("copyFunction", "clippyPanel", this);
			String baseUrl = WicketUtils.getGitblitURL(getRequest());
			ShockWaveComponent clippy = new ShockWaveComponent("clippy", baseUrl + "/clippy.swf");
			clippy.setValue("flashVars", "text=" + StringUtils.encodeURL(text));
			copyFragment.add(clippy);
			return copyFragment;
		} else {
			// javascript: manual copy & paste with modal browser prompt dialog
			Fragment copyFragment = new Fragment("copyFunction", "jsPanel", this);
			ContextImage img = WicketUtils.newImage("copyIcon", "clippy.png");
			img.add(new JavascriptTextPrompt("onclick", "Copy to Clipboard (Ctrl+C, Enter)", text));
			copyFragment.add(img);
			return copyFragment;
		}
	}

	protected String getProtocolPermissionDescription(RepositoryModel repository,
			RepositoryUrl repoUrl) {
		if (!urlPermissionsMap.containsKey(repoUrl.url)) {
			String note;
			if (repoUrl.hasPermission()) {
				note = null;
				String key;
				switch (repoUrl.permission) {
				case OWNER:
				case REWIND:
					key = "gb.rewindPermission";
					break;
				case DELETE:
					key = "gb.deletePermission";
					break;
				case CREATE:
					key = "gb.createPermission";
					break;
				case PUSH:
					key = "gb.pushPermission";
					break;
				case CLONE:
					key = "gb.clonePermission";
					break;
				default:
					key = null;
					note = getString("gb.viewAccess");
					break;
				}

				if (note == null) {
					String pattern = getString(key);
					String description = MessageFormat.format(pattern, repoUrl.permission.toString());
					note = description;
				}
			} else {
				String protocol;
				int protocolIndex = repoUrl.url.indexOf("://");
				if (protocolIndex > -1) {
					// explicit protocol specified
					protocol = repoUrl.url.substring(0, protocolIndex);
				} else {
					// implicit SSH url
					protocol = "ssh";
				}
				note = MessageFormat.format(getString("gb.externalPermissions"), protocol);
			}
			urlPermissionsMap.put(repoUrl.url, note);
		}
		return urlPermissionsMap.get(repoUrl.url);
	}

	protected Map<AccessRestrictionType, String> getAccessRestrictions() {
		if (accessRestrictionsMap == null) {
			accessRestrictionsMap = new HashMap<AccessRestrictionType, String>();
			for (AccessRestrictionType type : AccessRestrictionType.values()) {
				switch (type) {
				case NONE:
					accessRestrictionsMap.put(type, getString("gb.notRestricted"));
					break;
				case PUSH:
					accessRestrictionsMap.put(type, getString("gb.pushRestricted"));
					break;
				case CLONE:
					accessRestrictionsMap.put(type, getString("gb.cloneRestricted"));
					break;
				case VIEW:
					accessRestrictionsMap.put(type, getString("gb.viewRestricted"));
					break;
				}
			}
		}
		return accessRestrictionsMap;
	}

	protected Component createRepositoryIndicators(RepositoryModel repository) {
		Fragment fragment = new Fragment("repositoryIndicators", "indicatorsFragment", this);
		if (repository.isBare) {
			fragment.add(new Label("workingCopyIndicator").setVisible(false));
		} else {
			Fragment wc = new Fragment("workingCopyIndicator", "workingCopyFragment", this);
			Label lbl = new Label("workingCopy", getString("gb.workingCopy"));
			WicketUtils.setHtmlTooltip(lbl,  getString("gb.workingCopyWarning"));
			wc.add(lbl);
			fragment.add(wc);
		}

		boolean allowForking = app().settings().getBoolean(Keys.web.allowForking, true);
		if (!allowForking || user == null || !user.isAuthenticated) {
			// must be logged-in to fork, hide all fork controls
			fragment.add(new Label("forksProhibitedIndicator").setVisible(false));
		} else {
			String fork = app().repositories().getFork(user.username, repository.name);
			boolean hasFork = fork != null;
			boolean canFork = user.canFork(repository);

			if (hasFork || !canFork) {
				if (user.canFork() && !repository.allowForks) {
					// show forks prohibited indicator
					Fragment wc = new Fragment("forksProhibitedIndicator", "forksProhibitedFragment", this);
					Label lbl = new Label("forksProhibited", getString("gb.forksProhibited"));
					WicketUtils.setHtmlTooltip(lbl,  getString("gb.forksProhibitedWarning"));
					wc.add(lbl);
					fragment.add(wc);
				} else {
					// can not fork, no need for forks prohibited indicator
					fragment.add(new Label("forksProhibitedIndicator").setVisible(false));
				}
			} else if (canFork) {
				// can fork and we do not have one
				fragment.add(new Label("forksProhibitedIndicator").setVisible(false));
			}
		}
		return fragment;
	}
}
