/*
 * 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;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.URL;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

/**
 * Constant values used by Gitblit.
 * 
 * @author James Moger
 * 
 */
public class Constants {

	public static final String NAME = "Gitblit";

	public static final String FULL_NAME = "Gitblit - a pure Java Git solution";

	public static final String ADMIN_ROLE = "#admin";
	
	public static final String FORK_ROLE = "#fork";
	
	public static final String CREATE_ROLE = "#create";

	public static final String NOT_FEDERATED_ROLE = "#notfederated";
	
	public static final String NO_ROLE = "#none";
	
	public static final String EXTERNAL_ACCOUNT = "#externalAccount";

	public static final String PROPERTIES_FILE = "gitblit.properties";

	public static final String GIT_PATH = "/git/";

	public static final String ZIP_PATH = "/zip/";

	public static final String SYNDICATION_PATH = "/feed/";

	public static final String FEDERATION_PATH = "/federation/";

	public static final String RPC_PATH = "/rpc/";
	
	public static final String PAGES = "/pages/";
	
	public static final String SPARKLESHARE_INVITE_PATH = "/sparkleshare/";

	public static final String BORDER = "***********************************************************";

	public static final String FEDERATION_USER = "$gitblit";

	public static final String PROPOSAL_EXT = ".json";
	
	public static final String ENCODING = "UTF-8";
	
	public static final int LEN_SHORTLOG = 78;
	
	public static final int LEN_SHORTLOG_REFS = 60;
	
	public static final String DEFAULT_BRANCH = "default";
	
	public static final String CONFIG_GITBLIT = "gitblit";
	
	public static final String CONFIG_CUSTOM_FIELDS = "customFields";
	
	public static final String ISO8601 = "yyyy-MM-dd'T'HH:mm:ssZ";
	
	public static final String baseFolder = "baseFolder";
	
	public static final String baseFolder$ = "${" + baseFolder + "}";
	
	public static final String contextFolder$ = "${contextFolder}";
	
	public static final String HEAD = "HEAD";

	public static final String R_GITBLIT = "refs/gitblit/";
	
	public static final String R_HEADS = "refs/heads/";
	
	public static final String R_NOTES = "refs/notes/";
	
	public static final String R_CHANGES = "refs/changes/";
	
	public static final String R_PULL= "refs/pull/";

	public static final String R_TAGS = "refs/tags/";
	
	public static final String R_REMOTES = "refs/remotes/";

	public static String getVersion() {
		String v = Constants.class.getPackage().getImplementationVersion();
		if (v == null) {
			return "0.0.0-SNAPSHOT";
		}
		return v;
	}

	public static String getGitBlitVersion() {
		return NAME + " v" + getVersion();
	}
	
	public static String getBuildDate() {
		return getManifestValue("build-date", "PENDING");
	}
	
	private static String getManifestValue(String attrib, String defaultValue) {
		Class<?> clazz = Constants.class;
		String className = clazz.getSimpleName() + ".class";
		String classPath = clazz.getResource(className).toString();
		if (!classPath.startsWith("jar")) {
			// Class not from JAR
			return defaultValue;
		}
		try {
			String manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) + "/META-INF/MANIFEST.MF";
			Manifest manifest = new Manifest(new URL(manifestPath).openStream());
			Attributes attr = manifest.getMainAttributes();
			String value = attr.getValue(attrib);
			return value;
		} catch (Exception e) {
		}
		return defaultValue;
	}
	
	/**
	 * Enumeration representing the four access restriction levels.
	 */
	public static enum AccessRestrictionType {
		NONE, PUSH, CLONE, VIEW;

		public static AccessRestrictionType fromName(String name) {
			for (AccessRestrictionType type : values()) {
				if (type.name().equalsIgnoreCase(name)) {
					return type;
				}
			}
			return NONE;
		}

		public boolean exceeds(AccessRestrictionType type) {
			return this.ordinal() > type.ordinal();
		}

		public boolean atLeast(AccessRestrictionType type) {
			return this.ordinal() >= type.ordinal();
		}

		public String toString() {
			return name();
		}
		
		public boolean isValidPermission(AccessPermission permission) {
			switch (this) {
			case VIEW:
				// VIEW restriction
				// all access permissions are valid
				return true;
			case CLONE:
				// CLONE restriction
				// only CLONE or greater access permissions are valid
				return permission.atLeast(AccessPermission.CLONE);
			case PUSH:
				// PUSH restriction
				// only PUSH or greater access permissions are valid 
				return permission.atLeast(AccessPermission.PUSH);
			case NONE:
				// NO access restriction
				// all access permissions are invalid
				return false;
			}
			return false;
		}
	}
	
	/**
	 * Enumeration representing the types of authorization control for an
	 * access restricted resource.
	 */
	public static enum AuthorizationControl {
		AUTHENTICATED, NAMED;
		
		public static AuthorizationControl fromName(String name) {
			for (AuthorizationControl type : values()) {
				if (type.name().equalsIgnoreCase(name)) {
					return type;
				}
			}
			return NAMED;
		}
		
		public String toString() {
			return name();
		}
	}


	/**
	 * Enumeration representing the types of federation tokens.
	 */
	public static enum FederationToken {
		ALL, USERS_AND_REPOSITORIES, REPOSITORIES;

		public static FederationToken fromName(String name) {
			for (FederationToken type : values()) {
				if (type.name().equalsIgnoreCase(name)) {
					return type;
				}
			}
			return REPOSITORIES;
		}

		public String toString() {
			return name();
		}
	}

	/**
	 * Enumeration representing the types of federation requests.
	 */
	public static enum FederationRequest {
		POKE, PROPOSAL, PULL_REPOSITORIES, PULL_USERS, PULL_TEAMS, PULL_SETTINGS, PULL_SCRIPTS, STATUS;

		public static FederationRequest fromName(String name) {
			for (FederationRequest type : values()) {
				if (type.name().equalsIgnoreCase(name)) {
					return type;
				}
			}
			return PULL_REPOSITORIES;
		}

		public String toString() {
			return name();
		}
	}

	/**
	 * Enumeration representing the statii of federation requests.
	 */
	public static enum FederationPullStatus {
		PENDING, FAILED, SKIPPED, PULLED, MIRRORED, NOCHANGE, EXCLUDED;

		public static FederationPullStatus fromName(String name) {
			for (FederationPullStatus type : values()) {
				if (type.name().equalsIgnoreCase(name)) {
					return type;
				}
			}
			return PENDING;
		}

		@Override
		public String toString() {
			return name();
		}
	}

	/**
	 * Enumeration representing the federation types.
	 */
	public static enum FederationStrategy {
		EXCLUDE, FEDERATE_THIS, FEDERATE_ORIGIN;

		public static FederationStrategy fromName(String name) {
			for (FederationStrategy type : values()) {
				if (type.name().equalsIgnoreCase(name)) {
					return type;
				}
			}
			return FEDERATE_THIS;
		}

		public boolean exceeds(FederationStrategy type) {
			return this.ordinal() > type.ordinal();
		}

		public boolean atLeast(FederationStrategy type) {
			return this.ordinal() >= type.ordinal();
		}

		@Override
		public String toString() {
			return name();
		}
	}

	/**
	 * Enumeration representing the possible results of federation proposal
	 * requests.
	 */
	public static enum FederationProposalResult {
		ERROR, FEDERATION_DISABLED, MISSING_DATA, NO_PROPOSALS, NO_POKE, ACCEPTED;

		@Override
		public String toString() {
			return name();
		}
	}

	/**
	 * Enumeration representing the possible remote procedure call requests from
	 * a client.
	 */
	public static enum RpcRequest {
		// Order is important here.  anything above LIST_SETTINGS requires
		// administrator privileges and web.allowRpcManagement.
		CLEAR_REPOSITORY_CACHE, GET_PROTOCOL, LIST_REPOSITORIES, LIST_BRANCHES, GET_USER, LIST_SETTINGS,
		CREATE_REPOSITORY, EDIT_REPOSITORY, DELETE_REPOSITORY, 
		LIST_USERS, CREATE_USER, EDIT_USER, DELETE_USER, 
		LIST_TEAMS, CREATE_TEAM, EDIT_TEAM, DELETE_TEAM,
		LIST_REPOSITORY_MEMBERS, SET_REPOSITORY_MEMBERS, LIST_REPOSITORY_TEAMS, SET_REPOSITORY_TEAMS, 
		LIST_REPOSITORY_MEMBER_PERMISSIONS, SET_REPOSITORY_MEMBER_PERMISSIONS, LIST_REPOSITORY_TEAM_PERMISSIONS, SET_REPOSITORY_TEAM_PERMISSIONS, 
		LIST_FEDERATION_REGISTRATIONS, LIST_FEDERATION_RESULTS, LIST_FEDERATION_PROPOSALS, LIST_FEDERATION_SETS,
		EDIT_SETTINGS, LIST_STATUS;

		public static RpcRequest fromName(String name) {
			for (RpcRequest type : values()) {
				if (type.name().equalsIgnoreCase(name)) {
					return type;
				}
			}
			return null;
		}		

		public boolean exceeds(RpcRequest type) {
			return this.ordinal() > type.ordinal();
		}

		@Override
		public String toString() {
			return name();
		}
	}

	/**
	 * Enumeration of the search types.
	 */
	public static enum SearchType {
		AUTHOR, COMMITTER, COMMIT;
	
		public static SearchType forName(String name) {
			for (SearchType type : values()) {
				if (type.name().equalsIgnoreCase(name)) {
					return type;
				}
			}
			return COMMIT;
		}
	
		@Override
		public String toString() {
			return name().toLowerCase();
		}
	}
	
	/**
	 * The types of objects that can be indexed and queried.
	 */
	public static enum SearchObjectType {
		commit, blob, issue;

		static SearchObjectType fromName(String name) {
			for (SearchObjectType value : values()) {
				if (value.name().equals(name)) {
					return value;
				}
			}
			return null;
		}
	}
	
	/**
	 * The access permissions available for a repository. 
	 */
	public static enum AccessPermission {
		NONE("N"), EXCLUDE("X"), VIEW("V"), CLONE("R"), PUSH("RW"), CREATE("RWC"), DELETE("RWD"), REWIND("RW+"), OWNER("RW+");
		
		public static final AccessPermission [] NEWPERMISSIONS = { EXCLUDE, VIEW, CLONE, PUSH, CREATE, DELETE, REWIND };
		
		public static AccessPermission LEGACY = REWIND;
		
		public final String code;
		
		private AccessPermission(String code) {
			this.code = code;
		}

		public boolean atMost(AccessPermission perm) {
			return ordinal() <= perm.ordinal();
		}

		public boolean atLeast(AccessPermission perm) {
			return ordinal() >= perm.ordinal();
		}

		public boolean exceeds(AccessPermission perm) {
			return ordinal() > perm.ordinal();
		}
		
		public String asRole(String repository) {
			return code + ":" + repository;
		}
		
		@Override
		public String toString() {
			return code;
		}
		
		public static AccessPermission permissionFromRole(String role) {
			String [] fields = role.split(":", 2);
			if (fields.length == 1) {
				// legacy/undefined assume full permissions
				return AccessPermission.LEGACY;
			} else {
				// code:repository
				return AccessPermission.fromCode(fields[0]);
			}
		}
		
		public static String repositoryFromRole(String role) {
			String [] fields = role.split(":", 2);
			if (fields.length == 1) {
				// legacy/undefined assume full permissions
				return role;
			} else {
				// code:repository
				return fields[1];
			}
		}
		
		public static AccessPermission fromCode(String code) {
			for (AccessPermission perm : values()) {
				if (perm.code.equalsIgnoreCase(code)) {
					return perm;
				}
			}
			return AccessPermission.NONE;
		}
	}
	
	public static enum RegistrantType {
		REPOSITORY, USER, TEAM;
	}
	
	public static enum PermissionType {
		MISSING, ANONYMOUS, EXPLICIT, TEAM, REGEX, OWNER, ADMINISTRATOR;
	}
	
	public static enum GCStatus {
		READY, COLLECTING;
		
		public boolean exceeds(GCStatus s) {
			return ordinal() > s.ordinal();
		}
	}

	public static enum AuthenticationType {
		CREDENTIALS, COOKIE, CERTIFICATE, CONTAINER;
		
		public boolean isStandard() {
			return ordinal() <= COOKIE.ordinal();
		}
	}
	
	public static enum AccountType {
		LOCAL, EXTERNAL, LDAP, REDMINE, SALESFORCE, WINDOWS, PAM;
		
		public boolean isLocal() {
			return this == LOCAL;
		}
	}

	@Documented
	@Retention(RetentionPolicy.RUNTIME)
	public @interface Unused {
	}
}
