package com.chain.api;

import com.chain.exception.*;
import com.chain.http.*;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * A predicate to be satisfied when transferring assets.
 */
public class ControlProgram {
  /**
   * Hex-encoded string representation of the control program.
   */
  @SerializedName("control_program")
  public String program;

  /**
   * Generates hex representation of a "retire" control program.
   * @return
   */
  public static String retireProgram() {
    return "6a";
  }

  /**
   * Creates a batch of control programs.
   * @param ctx context object which makes requests to core
   * @param programs list of control program builder objects
   * @return a list of control programs
   * @throws APIException This exception is raised if the api returns errors while creating the control programs.
   * @throws BadURLException This exception wraps java.net.MalformedURLException.
   * @throws ConnectivityException This exception is raised if there are connectivity issues with the server.
   * @throws HTTPException This exception is raised when errors occur making http requests.
   * @throws JSONException This exception is raised due to malformed json requests or responses.
   */
  public static List<ControlProgram> createBatch(Context ctx, List<Builder> programs)
      throws ChainException {
    Type type = new TypeToken<List<ControlProgram>>() {}.getType();
    return ctx.request("create-control-program", programs, type);
  }

  /**
   * A builder class for control programs.
   */
  public static class Builder {
    /**
     * Specifies the type of control program.
     */
    public String type;

    /**
     * Parameters to the control program.
     */
    public Map<String, Object> params;

    /**
     * Default constructor, initializes the params object.
     */
    public Builder() {
      this.params = new HashMap<>();
    }

    /**
     * Creates a control program.
     * @param ctx context object which makes requests to core
     * @return a control program
     * @throws APIException This exception is raised if the api returns errors while creating the control program.
     * @throws BadURLException This exception wraps java.net.MalformedURLException.
     * @throws ConnectivityException This exception is raised if there are connectivity issues with the server.
     * @throws HTTPException This exception is raised when errors occur making http requests.
     * @throws JSONException This exception is raised due to malformed json requests or responses.
     */
    public ControlProgram create(Context ctx) throws ChainException {
      return ctx.singletonBatchRequest(
          "create-control-program", Arrays.asList(this), ControlProgram.class);
    }

    /**
     * Specifies an account to link to the control program.<br>
     * An id is used to distinguish the account.
     * @param accountId id of the account
     * @return updated builder object
     */
    public Builder controlWithAccountById(String accountId) {
      this.type = "account";
      this.addParameter("account_id", accountId);
      return this;
    }

    /**
     * Specifies an account to link to the control program.<br>
     * An alias is used to distinguish the account.
     * @param accountAlias alias of the account
     * @return updated builder object
     */
    public Builder controlWithAccountByAlias(String accountAlias) {
      this.type = "account";
      this.addParameter("account_alias", accountAlias);
      return this;
    }

    /**
     * Sets the type attribute of the control program.
     * @param type the type of control program
     * @return updated builder object
     */
    public Builder setType(String type) {
      this.type = type;
      return this;
    }

    /**
     * Adds a parameter to the control program.
     * @param key the key of the param field
     * @param value the value of the param field
     * @return updated builder object
     */
    public Builder addParameter(String key, Object value) {
      this.params.put(key, value);
      return this;
    }

    /**
     * Sets the parameters object.<br>
     * <strong>Note:</strong> any existing parameter fields will be replaced.
     * @param parameters parameters object
     * @return updated builder object
     */
    public Builder setParameters(Map<String, Object> parameters) {
      this.params = parameters;
      return this;
    }
  }
}

@@ -127,81 +127,8 @@
 me;%0A
-import com.google.gson.reflect.TypeToken;%0A%0Aimport java.lang.reflect.Type;
 %0Aimp
@@ -1333,20 +1333,29 @@
  static 
-List
+BatchResponse
 %3CControl
@@ -1446,76 +1446,8 @@
 n %7B%0A
-    Type type = new TypeToken%3CList%3CControlProgram%3E%3E() %7B%7D.getType();%0A
     
@@ -1457,17 +1457,22 @@
 urn ctx.
-r
+batchR
 equest(%22
@@ -1506,20 +1506,36 @@
 ograms, 
-type
+ControlProgram.class
 );%0A  %7D%0A%0A

return BatchResponse from ControlProgram.createBatch