package co.gem.round;

import co.gem.round.coinop.MultiWallet;
import co.gem.round.coinop.util.Network;
import co.gem.round.crypto.EncryptedMessage;
import co.gem.round.crypto.PassphraseBox;
import co.gem.round.patchboard.Client;
import co.gem.round.patchboard.Resource;
import com.google.gson.JsonObject;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

/**
 * UserCollection provides functionality to create users and generate a collection of users.
 * @author Julian Vergel de Dios (julian@gem.co) on 12/18/14.
 */
public class UserCollection extends BaseCollection<User> {
  public UserCollection(Resource resource, Round round) { super(resource, round); }

  /**
   * Create a User on the Gem platform.  At the time of user creation a default HD multi-sig wallet is created
   * labeled "default".  The wallet requires a passphrase to encrypt the primary key and the network for address
   * creation.
   * @param email of the user
   * @param firstName of the user
   * @param lastName of the user
   * @param passphrase to encrypt the primary seed
   * @param blockchain network for the wallet.  Either mainnet or testnet
   * @return User wrapper were you can get the user object to initiate begin/complete device authentication.  This is
   * depricated and will be replaced with returning only a User object.
   * @throws Client.UnexpectedStatusCodeException
   * @throws IOException
   * @throws InvalidKeySpecException
   * @throws NoSuchAlgorithmException
   */
  public User create(String email, String firstName, String lastName, String passphrase, String blockchain, String deviceName)
      throws Client.UnexpectedStatusCodeException, IOException,
      InvalidKeySpecException, NoSuchAlgorithmException{
    MultiWallet multiWallet = MultiWallet.generate(Network.blockchainNetwork(blockchain));
    String primaryPrivateSeed = multiWallet.serializedPrimaryPrivateSeed();
    EncryptedMessage encryptedPrivateSeed = PassphraseBox.encrypt(passphrase, primaryPrivateSeed);

    String network;
    if (multiWallet.blockchain() == MultiWallet.Blockchain.MAINNET)
      network = "bitcoin";
    else
      network = "bitcoin_testnet";

    JsonObject wallet = new JsonObject();
    wallet.addProperty("name", "default");
    wallet.addProperty("network", network);
    wallet.addProperty("primary_public_seed", multiWallet.serializedPrimaryPublicKey());
    wallet.add("primary_private_seed", encryptedPrivateSeed.asJsonObject());

    JsonObject payload = new JsonObject();
    payload.addProperty("email", email);
    payload.addProperty("device_name", deviceName);
    payload.add("default_wallet", wallet);
    payload.addProperty("first_name", firstName);
    payload.addProperty("last_name", lastName);

    Resource resource = this.resource.action("create", payload);
    User user = new User(resource, round);
    return user;
  }

  @Override
  public void populateCollection(Iterable<Resource> collection) {
    for (Resource resource : collection) {
      User user = new User(resource, round);
      add(user.email(), user);
    }
  }
}

@@ -734,16 +734,17 @@
 nd); %7D%0A%0A
+%0A
   /**%0A  
@@ -1659,97 +1659,1378 @@
 ain,
- String deviceName)%0A      throws Client.UnexpectedStatusCodeException, IOException,%0A     
+%0A                     String deviceName) throws NoSuchAlgorithmException, Client.UnexpectedStatusCodeException,%0A      InvalidKeySpecException, IOException %7B%0A    return create(email, firstName, lastName, passphrase, blockchain, deviceName, null);%0A  %7D%0A%0A  /**%0A   * Create a User on the Gem platform.  At the time of user creation a default HD multi-sig wallet is created%0A   * labeled %22default%22.  The wallet requires a passphrase to encrypt the primary key and the network for address%0A   * creation.%0A   * @param email of the user%0A   * @param firstName of the user%0A   * @param lastName of the user%0A   * @param passphrase to encrypt the primary seed%0A   * @param blockchain network for the wallet.  Either mainnet or testnet%0A   * @param redirectUri the user is sent to after confirming his/her email%0A   * @return User wrapper were you can get the user object to initiate begin/complete device authentication.  This is%0A   * depricated and will be replaced with returning only a User object.%0A   * @throws Client.UnexpectedStatusCodeException%0A   * @throws IOException%0A   * @throws InvalidKeySpecException%0A   * @throws NoSuchAlgorithmException%0A   */%0A  public User create(String email, String firstName, String lastName, String passphrase, String blockchain,%0A                     String deviceName, String redirectUri)%0A      throws Client.UnexpectedStatusCodeException, IOException,
  Inv
@@ -3075,16 +3075,17 @@
 xception
+ 
 %7B%0A    Mu
@@ -3797,24 +3797,24 @@
 Object());%0A%0A
-
     JsonObje
@@ -3840,24 +3840,117 @@
 onObject();%0A
+    if (redirectUri != null) %7B%0A      payload.addProperty(%22redirect_uri%22, redirectUri);%0A    %7D%0A
     payload.

Add redirect_uri to Users#create