package com.chain.api;

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

import java.lang.reflect.Type;
import java.util.*;

/**
 * A single Account on the Chain Core, capable of spending or receiving assets in a transaction
 */
public class Account {
    /**
     * Unique account identifier, optionally user defined
     */
    public String id;

    /**
     * The number of public keys required to signing transactions for the account
     */
    public int quorum;

    /**
     * The list of public keys attached to the account
     */
    public List<String> xpubs;

    /**
     * User-specified tag structure for the account
     */
    public Map<String, Object> tags;

    public Account setTags(Map<String, Object> tags) {
        this.tags = tags;
        return this;
    }

    public Account addTag(String key, Object value) {
        this.tags.put(key, value);
        return this;
    }

    public Account removeTag(String key) {
        this.tags.remove(key);
        return this;
    }

    public Account updateTags(Context ctx) throws ChainException {
        HashMap<String, Object> requestBody = new HashMap<>();
        requestBody.put("account_id", this.id);
        requestBody.put("tags", this.tags);
        return ctx.request("set-account-tags", requestBody, Account.class);
    }

    public static class Items extends PagedItems<Account> {
        public Items getPage() throws ChainException {
            Items items = this.context.request("list-accounts", this.query, Items.class);
            items.setContext(this.context);
            return items;
        }
    }
    public static class QueryBuilder extends BaseQueryBuilder<QueryBuilder> {
        public Items execute(Context ctx) throws ChainException {
            Items items = new Items();
            items.setContext(ctx);
            items.setQuery(this.query);
            return items.getPage();
        }
    }

    public static class Builder {
        public int quorum;
        public List<String> xpubs;
        public Map<String, Object> tags;
        @SerializedName("client_token")
        private String clientToken;

        public Builder() {
            this.tags = new HashMap<>();
            this.xpubs = new ArrayList<>();
        }

        /**
         * Creates an account object.
         *
         * @param ctx context object that makes requests to core
         * @return an account object
         * @throws ChainException
         */
        public Account create(Context ctx)
        throws ChainException {
            List<Account> accts = Account.Builder.create(ctx, Arrays.asList(this));
            return accts.get(0);
        }

        /**
         * Creates a batch of account objects.
         *
         * @param ctx context object that makes requests to core
         * @return an account object
         * @throws ChainException
         */
        public static List<Account> create(Context ctx, List<Builder> accts)
        throws ChainException {
            for (Builder acct : accts) {
                acct.clientToken = UUID.randomUUID().toString();
            }
            Type type = new TypeToken<List<Account>>() {}.getType();
            return ctx.request("create-account", accts, type);
        }

        public Builder setQuorum(int quorum) {
            this.quorum = quorum;
            return this;
        }

        public Builder addXpub(String xpub) {
            this.xpubs.add(xpub);
            return this;
        }

        public Builder setXpubs(List<String> xpubs) {
            this.xpubs = new ArrayList<>();
            for (String xpub : xpubs) {
                this.xpubs.add(xpub);
            }
            return this;
        }

        public Builder addTag(String key, Object value) {
            this.tags.put(key, value);
            return this;
        }

        public Builder setTags(Map<String, Object> tags) {
            this.tags = tags;
            return this;
        }
    }
}

@@ -408,33 +408,88 @@
 fier
-, optionally user defined
+%0A     */%0A    public String id;%0A%0A    /**%0A     * User specified, unique identifier
 %0A   
@@ -503,34 +503,37 @@
   public String 
-id
+alias
 ;%0A%0A    /**%0A     
@@ -2119,16 +2119,45 @@
 ilder %7B%0A
+        public String alias;%0A
         
@@ -3445,32 +3445,148 @@
 pe);%0A        %7D%0A%0A
+        public Builder setAlias(String alias) %7B%0A            this.alias = alias;%0A            return this;%0A        %7D%0A%0A
         public B

add member alias to Account class