package com.filestack.model.transform.base;

import com.filestack.model.FileLink;
import com.filestack.model.FilestackClient;
import com.filestack.model.transform.tasks.StoreOptions;
import com.filestack.util.FilestackService;
import com.google.gson.JsonObject;

import java.io.IOException;

/**
 * {@link Transform Transform} subclass for image transformations.
 */
public class ImageTransform extends Transform {

  public ImageTransform(FilestackClient fsClient, String source) {
    super(fsClient, source);
  }

  public ImageTransform(FileLink fileLink) {
    super(fileLink);
  }

  /**
   * Debugs the transformation as built so far, returning explanations of any issues.
   *
   * @return {@link JsonObject JSON} report for transformation
   * @throws IOException for network failures, invalid handles, or invalid security
   */
  public JsonObject debug() throws IOException {
    String tasksString = getTasksString();

    if (apiKey != null) {
      return processService.debugExternal(apiKey, tasksString, source).execute().body();
    } else {
      return processService.debug(tasksString, source).execute().body();
    }
  }

  public FileLink store() throws IOException {
    return store(null);
  }

  /**
   * Stores the result of a transformation into a new file.
   * https://www.filestack.com/docs/image-transformations/store
   *
   * @param storeOptions configure where and how your file is stored
   * @return new {@link FileLink FileLink} pointing to the file
   * @throws IOException for network failures, invalid handles, or invalid security
   */
  public FileLink store(StoreOptions storeOptions) throws IOException {
    if (storeOptions == null) {
      storeOptions = new StoreOptions();
    }
    addTask(storeOptions);

    FilestackService.Process.StoreResponse response;
    String tasksString = getTasksString();

    if (apiKey != null) {
      response = processService.storeExternal(apiKey, tasksString, source).execute().body();
    } else {
      response = processService.store(tasksString, source).execute().body();
    }

    String handle = response.getUrl().split("/")[3];
    return new FileLink(apiKey, handle, security);
  }

  /**
   * Add a new transformation to the chain.
   * Tasks are executed in the order they are added.
   *
   * @param task any one of the available {@link ImageTransformTask ImageTransformTask} subclasses
   */
  public ImageTransform addTask(ImageTransformTask task) {
    if (task == null) {
      throw new IllegalArgumentException("Cannot add null task to image transform");
    }
    tasks.add(task);
    return this;
  }
}

@@ -267,27 +267,137 @@
 ort 
-java.io.IOException
+io.reactivex.Single;%0Aimport io.reactivex.schedulers.Schedulers;%0A%0Aimport java.io.IOException;%0Aimport java.util.concurrent.Callable
 ;%0A%0A/
@@ -2709,11 +2709,1026 @@
 his;%0A  %7D
+%0A%0A  // Async method wrappers%0A%0A  /**%0A   * Async, observable version of %7B@link #debug()%7D.%0A   * Throws same exceptions.%0A   */%0A  public Single%3CJsonObject%3E debugAsync() %7B%0A    return Single.fromCallable(new Callable%3CJsonObject%3E() %7B%0A      @Override%0A      public JsonObject call() throws Exception %7B%0A        return debug();%0A      %7D%0A    %7D)%0A        .subscribeOn(Schedulers.io())%0A        .observeOn(Schedulers.single());%0A  %7D%0A%0A  /**%0A   * Async, observable version of %7B@link #store()%7D.%0A   * Throws same exceptions.%0A   */%0A  public Single%3CFileLink%3E storeAsync() %7B%0A    return storeAsync(null);%0A  %7D%0A%0A  /**%0A   * Async, observable version of %7B@link #store(StoreOptions)%7D.%0A   * Throws same exceptions.%0A   */%0A  public Single%3CFileLink%3E storeAsync(final StoreOptions storeOptions) %7B%0A    return Single.fromCallable(new Callable%3CFileLink%3E() %7B%0A      @Override%0A      public FileLink call() throws Exception %7B%0A        return store(storeOptions);%0A      %7D%0A    %7D)%0A        .subscribeOn(Schedulers.io())%0A        .observeOn(Schedulers.single());%0A  %7D
 %0A%7D%0A

Add async methods to ImageTransform