package us.kbase.auth2.service.api;

import static us.kbase.auth2.lib.Utils.dateToSec;

import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

import us.kbase.auth2.lib.AuthUser;
import us.kbase.auth2.lib.Authentication;
import us.kbase.auth2.lib.UserName;
import us.kbase.auth2.lib.exceptions.ErrorType;
import us.kbase.auth2.lib.exceptions.AuthException;
import us.kbase.auth2.lib.exceptions.InvalidTokenException;
import us.kbase.auth2.lib.exceptions.NoSuchUserException;
import us.kbase.auth2.lib.exceptions.UnauthorizedException;
import us.kbase.auth2.lib.storage.exceptions.AuthStorageException;
import us.kbase.auth2.lib.token.HashedToken;
import us.kbase.auth2.lib.token.IncomingToken;

@Path("/api/legacy/globus")
public class LegacyGlobus {

	//TODO TEST
	//TODO JAVADOC
	
	@Inject
	private Authentication auth;
	
	// note that access_token_hash is not returned in the structure
	// also note that unlike the globus api, this does not refresh the token
	// also note that the error structure is completely different. 
	@GET
	@Path("/goauth/token")
	@Produces(MediaType.APPLICATION_JSON)
	public Map<String, Object> introspectToken(
			@HeaderParam("x-globus-goauthtoken") final String xtoken,
			@HeaderParam("globus-goauthtoken") String token,
			@QueryParam("grant_type") final String grantType)
			throws AuthStorageException, AuthException {

		if (!"client_credentials".equals(grantType)) {
			throw new AuthException(ErrorType.UNSUPPORTED_OP,
					"Only client_credentials grant_type supported. Got " +
					grantType);
		}
		token = getGlobusToken(xtoken, token);
		final HashedToken ht;
		try {
			ht = auth.getToken(new IncomingToken(token));
		} catch (InvalidTokenException e) {
			// globus throws a 403 instead of a 401
			throw new UnauthorizedException(
					e.getErr(), "Authentication failed.");
		}
		final long created = dateToSec(ht.getCreationDate());
		final long expires = dateToSec(ht.getExpirationDate());
		final Map<String, Object> ret = new HashMap<>();
		ret.put("access_token", token);
		ret.put("client_id", ht.getUserName().getName());
		ret.put("expires_in", expires - dateToSec(new Date()));
		ret.put("expiry", expires);
		ret.put("issued_on", created);
		ret.put("lifetime", expires - created);
		ret.put("refresh_token", "");
		ret.put("scopes", new LinkedList<String>());
		ret.put("token_id", ht.getId().toString());
		ret.put("token_type", "Bearer");
		ret.put("user_name", ht.getUserName().getName());
		return ret;
	}

	private String getGlobusToken(final String xtoken, String token)
			throws UnauthorizedException {
		if (token == null || token.isEmpty()) {
			token = xtoken;
			if (token == null || token.isEmpty()) {
				// globus throws a 403 instead of a 401
				throw new UnauthorizedException(ErrorType.NO_TOKEN, "");
			}
		}
		return token;
	}
	
	// note does not return identity_id
	// note error structure is completely different
	@GET
	@Path("/users/{user}/")
	@Produces(MediaType.APPLICATION_JSON)
	public Map<String, Object> getUser(
			@HeaderParam("x-globus-goauthtoken") final String xtoken,
			@HeaderParam("globus-goauthtoken") String token,
			@PathParam("user") final String user)
			throws UnauthorizedException, AuthStorageException,
			NoSuchUserException {
		
		token = getGlobusToken(xtoken, token);
		final AuthUser u;
		try {
			u = auth.getUser(new IncomingToken(token), new UserName(user));
		} catch (InvalidTokenException e) {
			// globus throws a 403 instead of a 401
			throw new UnauthorizedException(
					e.getErr(), "Authentication failed.");
		}
		final Map<String, Object> ret = new HashMap<>();
		ret.put("username", u.getUserName().getName());
		ret.put("email_validated", false);
		ret.put("ssh_pubkeys", new LinkedList<String>());
		ret.put("resource_type", "users");
		ret.put("full_name", u.getFullName());
		ret.put("organization", null);
		ret.put("fullname", u.getFullName());
		ret.put("user_name", u.getUserName().getName());
		ret.put("email", u.getEmail());
		ret.put("custom_fields", new HashMap<String,String>());
		return ret;
	}
}

@@ -3355,33 +3355,28 @@
 rParam(%22
-globus-goauthtoke
+authorizatio
 n%22) Stri
@@ -3506,18 +3506,243 @@
 ption %7B%0A
-
 %09%09
+if (token != null) %7B%0A%09%09%09final String%5B%5D bits = token.trim().split(%22%5C%5Cs+%22);%0A%09%09%09if (bits.length != 2) %7B%0A%09%09%09%09throw new UnauthorizedException(%0A%09%09%09%09%09%09ErrorType.NO_TOKEN, %22Invalid authorization header%22);%0A%09%09%09%7D%0A%09%09%09token = bits%5B1%5D;%0A%09%09%7D
 %0A%09%09token

Fix allowed headers for globus /users endpoint