package co.omise.models;

import com.google.common.collect.ImmutableMap;
import okhttp3.FormBody;
import okhttp3.RequestBody;

/**
 * Params class encapsulate request parameterization and provides a way to builds a parameter builder
 * for resource operations. This class is meant to be subclassed and used in one the following ways:
 * <ul>
 * <li>Wrap the {@link #add(String, String)} in a builder method to appends key/value pair to the {@link FormBody} request body.</li>
 * <li>Overrides the {@link #query()} method to add query string parameters.</li>
 * <li>Overrides the {@link #body()} method to returns a custom OkHttp {@link RequestBody}.</li>
 * </ul>
 * <p>
 * For an example, see the {@link ScopedList.Options} or the {@link Charge.Create} class
 * </p>
 *
 * @see ScopedList.Options
 * @see Charge.Create
 */
public abstract class Params {
    private FormBody.Builder formBuilder = null;

    /**
     * Returns the query string to add to an HTTP operation's URL.
     *
     * @return An {@link ImmutableMap} containing keys and values to adds to the URL.
     */
    public ImmutableMap<String, String> query() {
        return ImmutableMap.of();
    }

    /**
     * Returns the {@link RequestBody} to send with the HTTP request. The default implementation automatically
     * builds and returns a {@link FormBody} from values added with the {@link #add(String, String)} method.
     *
     * @return An {@link RequestBody} to send with the HTTP request.
     */
    public RequestBody body() {
        return formBuilder == null ? null : formBuilder.build();
    }

    /**
     * Adds a key-value pair for building a {@link FormBody}.
     *
     * @param name  The name of the form field.
     * @param value The value of the form field.
     */
    protected void add(String name, String value) {
        if (formBuilder == null) {
            formBuilder = new FormBody.Builder();
        }

        // TODO: test
        if (value != null) {
            formBuilder = formBuilder.add(name, value);
        }
    }
}

@@ -19,16 +19,44 @@
 odels;%0A%0A
+import co.omise.Serializer;%0A
 import c
@@ -109,24 +109,25 @@
 okhttp3.
-FormBody
+MediaType
 ;%0Aimport
@@ -149,16 +149,83 @@
 tBody;%0A%0A
+import java.io.ByteArrayOutputStream;%0Aimport java.io.IOException;%0A%0A
 /**%0A * P
@@ -395,153 +395,157 @@
 and 
-u
 se
-d in one the following ways:
+rialized to JSON to send along%0A * with any API request.
 %0A * %3C
-ul
+p
 %3E%0A * 
-%3Cli%3EWrap the %7B@link #add(String, String)%7D in a builder method to appends key/value pair to 
+Subclass should:%0A * %3C/p%3E%0A * %3Cul%3E%0A * %3Cli%3EAnnotate any JSON properties wi
 th
-e
  %7B@link 
 Form
@@ -544,31 +544,54 @@
 ink 
-FormBody%7D request body.
+com.fasterxml.jackson.annotation.JsonProperty%7D
 %3C/li
@@ -708,16 +708,26 @@
 k #body(
+Serializer
 )%7D metho
@@ -997,43 +997,99 @@
 ate 
-FormBody.Builder formBuilder = null
+static final MediaType JSON_MEDIA_TYPE = MediaType.parse(%22application/json; charset=utf-8%22)
 ;%0A%0A 
@@ -1463,550 +1463,482 @@
 ion 
-automatically%0A     * builds and returns a %7B@link FormBody%7D from values added with the %7B@link #add(String, String)%7D method.%0A     *%0A     * @return An %7B@link RequestBody%7D to send with the HTTP request.
+serializes%0A     * the instance into JSON format and builds an HTTP %7B@link RequestBody%7D containing the serialized data.%0A     *%0A     * @param serializer The %7B@link Serializer%7D to use to serialize parameter data. Or %60null%60 to use the default
 %0A     *
-/%0A
     
-public RequestBody body() %7B%0A        return formBuilder == null ? null : formBuilder.build();%0A    %7D%0A%0A    /**%0A     * Adds a key-value pair for building a %7B@link FormBody%7D.%0A     *%0A     * @param name  The name of the form field.%0A     * @param value The value of the form field.%0A     */%0A    protected void add(String name, String value)
+               serializer.%0A     * @return An %7B@link RequestBody%7D to send with the HTTP request.%0A     * @throws IOException on serialization errors.%0A     */%0A    public RequestBody body(Serializer serializer) throws IOException
  %7B%0A 
@@ -1948,25 +1948,24 @@
     if (
-formBuild
+serializ
 er == nu
@@ -1986,161 +1986,183 @@
     
-formBuilder = new FormBody.Builder();%0A        %7D%0A%0A        // TODO: test%0A        if (value != null) %7B%0A            formBuilder = formBuilder.add(n
+serializer = Serializer.defaultSerializer();%0A        %7D%0A%0A        ByteArrayOutputStream stream = new ByteArrayOutputStream(4096);%0A        serializer.serializeParams(stre
 am
-e
 , 
-value
+this
 );%0A 
@@ -2168,17 +2168,81 @@
         
-%7D
+return RequestBody.create(JSON_MEDIA_TYPE, stream.toByteArray());
 %0A    %7D%0A%7D

Switch Params.body implementation from FormBody to using Serializer.