package com.filestack.transforms;

import com.filestack.FileLink;
import com.filestack.FilestackClient;
import com.filestack.Security;
import com.filestack.util.FsService;

import java.util.ArrayList;

import okhttp3.HttpUrl;

/**
 * Base class for file transformations and conversions.
 */
public class Transform {
  String apiKey;
  String source;
  Security security;

  ArrayList<TransformTask> tasks;

  FsService fsService;

  Transform(FilestackClient fsClient, String url) {
    this(fsClient, null, url);
  }

  Transform(FileLink fileLink) {
    this(null, fileLink, null);
  }

  Transform(FilestackClient fsClient, FileLink fileLink, String url) {
    if (fsClient != null) {
      this.apiKey = fsClient.getApiKey();
      this.source = url;
      this.fsService = fsClient.getFsService();
    } else {
      this.source = fileLink.getHandle();
      this.fsService = fileLink.getFsService();
    }

    this.tasks = new ArrayList<>();

    Security security = fsClient != null ? fsClient.getSecurity() : fileLink.getSecurity();
    this.security = security;
    if (security != null) {
      TransformTask securityTask = new TransformTask("security");
      securityTask.addOption("policy", security.getPolicy());
      securityTask.addOption("signature", security.getSignature());
      this.tasks.add(securityTask);
    }
  }

  /**
   * Format tasks into single string to insert into request.
   */
  String getTasksString() {
    if (tasks.size() == 0) {
      return "";
    }

    StringBuilder stringBuilder = new StringBuilder();
    for (TransformTask task : tasks) {
      stringBuilder.append(task.toString()).append('/');
    }
    stringBuilder.deleteCharAt(stringBuilder.length() - 1);
    return stringBuilder.toString();
  }

  /**
   * Generates a URL of the transformation.
   * Includes the related {@link FileLink FileLink's} policy and signature.
   *
   * @return transformation URL
   */
  public String url() {
    String tasksString = getTasksString();
    HttpUrl httpUrl;

    if (apiKey != null) {
      httpUrl = fsService.transformExt(apiKey, tasksString, source).request().url();
    } else {
      httpUrl = fsService.transform(tasksString, source).request().url();
    }

    // When building the request we add a / between tasks
    // Because that entire task string is added as a single path variable, the / is URL encoded
    // That's a little confusing so we're replacing "%2F" with "/" for a more expected URL
    return httpUrl.toString().replace("%2F", "/");
  }
}

@@ -153,76 +153,574 @@
 ack.
-util.FsService;%0A%0Aimport java.util.ArrayList;%0A%0Aimport okhttp3.HttpUrl
+errors.InternalException;%0Aimport com.filestack.errors.InvalidParameterException;%0Aimport com.filestack.errors.PolicySignatureException;%0Aimport com.filestack.errors.ResourceNotFoundException;%0Aimport com.filestack.util.FsService;%0Aimport com.filestack.util.Util;%0Aimport com.google.gson.Gson;%0Aimport com.google.gson.JsonObject;%0Aimport io.reactivex.Single;%0Aimport io.reactivex.schedulers.Schedulers;%0Aimport java.io.IOException;%0Aimport java.util.ArrayList;%0Aimport java.util.concurrent.Callable;%0Aimport okhttp3.HttpUrl;%0Aimport okhttp3.ResponseBody;%0Aimport retrofit2.Response
 ;%0A%0A/
@@ -3009,11 +3009,1489 @@
 /%22);%0A  %7D
+%0A%0A  public ResponseBody getContent()%0A      throws IOException, PolicySignatureException, ResourceNotFoundException,%0A             InvalidParameterException, InternalException %7B%0A%0A    String tasksString = getTasksString();%0A    Response%3CResponseBody%3E response;%0A%0A    if (apiKey != null) %7B%0A      response = fsService.transformExt(apiKey, tasksString, source).execute();%0A    %7D else %7B%0A      response = fsService.transform(tasksString, source).execute();%0A    %7D%0A%0A    Util.checkResponseAndThrow(response);%0A%0A    return response.body();%0A  %7D%0A%0A  public JsonObject getContentJson()%0A      throws IOException, PolicySignatureException, ResourceNotFoundException,%0A      InvalidParameterException, InternalException %7B%0A%0A    ResponseBody body = getContent();%0A%0A    Gson gson = new Gson();%0A    return gson.fromJson(body.charStream(), JsonObject.class);%0A  %7D%0A%0A  // Async method wrappers%0A%0A  public Single%3CResponseBody%3E getContentAsync() %7B%0A    return Single.fromCallable(new Callable%3CResponseBody%3E() %7B%0A      @Override%0A      public ResponseBody call() throws Exception %7B%0A        return getContent();%0A      %7D%0A    %7D)%0A        .subscribeOn(Schedulers.io())%0A        .observeOn(Schedulers.single());%0A  %7D%0A%0A  public Single%3CJsonObject%3E getContentJsonAsync() %7B%0A    return Single.fromCallable(new Callable%3CJsonObject%3E() %7B%0A      @Override%0A      public JsonObject call() throws Exception %7B%0A        return getContentJson();%0A      %7D%0A    %7D)%0A        .subscribeOn(Schedulers.io())%0A        .observeOn(Schedulers.single());%0A  %7D
 %0A%7D%0A

Add getContent and getContentJson methods to Transform