package us.kbase.auth2.lib.user;

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

import java.time.Instant;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import com.google.common.base.Optional;

import us.kbase.auth2.lib.DisplayName;
import us.kbase.auth2.lib.EmailAddress;
import us.kbase.auth2.lib.PolicyID;
import us.kbase.auth2.lib.Role;
import us.kbase.auth2.lib.UserDisabledState;
import us.kbase.auth2.lib.UserName;
import us.kbase.auth2.lib.identity.RemoteIdentityWithLocalID;

/** A new, non-local user. E.g. the user is associated with at least one 3rd party identity.
 * 
 * @author gaprice@lbl.gov
 *
 */
public class NewUser extends AuthUser {
	
	/** Create a new user.
	 * @param userName the name of the user.
	 * @param displayName the display name of the user.
	 * @param created the date the user was created.
	 * @param remoteIdentity the 3rd party identity associated with this user.
	 * @param email the email address of the user.
	 * @param policyIDs the policy IDs associated with this user.
	 * @param lastLogin the date of the user's last login. If this time is before the created
	 * date (e.g. the time this constructor is called) it will be silently modified to match
	 * the creation date.
	 */
	private NewUser(
			final UserName userName,
			final DisplayName displayName,
			final Instant created,
			final RemoteIdentityWithLocalID remoteIdentity,
			final EmailAddress email,
			final Set<Role> roles,
			final Set<String> customRoles,
			final Set<PolicyID> policyIDs,
			final Optional<Instant> lastLogin,
			final UserDisabledState disabledState) {
		super(userName, displayName, created, new HashSet<>(Arrays.asList(remoteIdentity)), email,
				roles, customRoles, policyIDs, lastLogin, disabledState);
	}

	public RemoteIdentityWithLocalID getIdentity() {
		if (getIdentities().size() != 1) {
			// this is untestable without some nutty reflection stuff, look into it later
			// should never happen since AuthUser is immutable
			throw new IllegalStateException("new user must have exactly one identity");
		}
		return getIdentities().iterator().next();
	}
	
	public static Builder getBuilder(
			final UserName userName,
			final DisplayName displayName,
			final Instant created,
			final RemoteIdentityWithLocalID remoteIdentity) {
		//TODO NOW JAVADOC
		return new Builder(userName, displayName, created, remoteIdentity);
	}
	
	public static class Builder extends AbstractBuilder<Builder> {

		private final RemoteIdentityWithLocalID remoteIdentity;
		
		private Builder(
				final UserName userName,
				final DisplayName displayName,
				final Instant created,
				final RemoteIdentityWithLocalID remoteIdentity) {
			//TODO NOW JAVADOC
			super(userName, displayName, created);
			if (UserName.ROOT.equals(userName)) {
				throw new IllegalArgumentException("Standard users cannot be root");
			}
			nonNull(remoteIdentity, "remoteIdentity");
			this.remoteIdentity = remoteIdentity;
		}
		
		Builder getThis() {
			return this;
		}
		
		public NewUser build() {
			return new NewUser(userName, displayName, created, remoteIdentity, email, roles,
					customRoles, policyIDs, lastLogin, disabledState);
		}
		
	}
	
}

@@ -572,16 +572,15 @@
 ith 
-at least
+exactly
  one
@@ -1766,16 +1766,84 @@
 e);%0A%09%7D%0A%0A
+%09/** Get the user's remote identity.%0A%09 * @return the identity.%0A%09 */%0A
 %09public 
@@ -2180,32 +2180,311 @@
 ().next();%0A%09%7D%0A%09%0A
+%09/** Get a builder for a new standard user.%0A%09 * @param userName the user's user name.%0A%09 * @param displayName the user's display name.%0A%09 * @param created the user's creation date.%0A%09 * @param remoteIdentity the remote identity associated with the user.%0A%09 * @return a builder.%0A%09 */%0A
 %09public static B
@@ -2643,37 +2643,16 @@
 tity) %7B%0A
-%09%09//TODO NOW JAVADOC%0A
 %09%09return
@@ -2718,16 +2718,77 @@
 );%0A%09%7D%0A%09%0A
+%09/** A NewUser builder.%0A%09 * @author gaprice@lbl.gov%0A%09 *%0A%09 */%0A
 %09public 
@@ -3073,30 +3073,8 @@
 ) %7B%0A
-%09%09%09//TODO NOW JAVADOC%0A
 %09%09%09s
@@ -3366,19 +3366,70 @@
 is;%0A%09%09%7D%0A
-
 %09%09%0A
+%09%09/** Build the user.%0A%09%09 * @return the user.%0A%09%09 */%0A
 %09%09public

Update NewUser javadoc