package com.castlabs.reactnative.network;

import android.net.Uri;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.castlabs.android.network.Request;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;

/**
 * The completable request.
 */
@RequiresApi(api = Build.VERSION_CODES.N)
public class RequestCompleter {
  private final @NonNull CompletableFuture<Request> future;
  private final @NonNull Request request;

  public final @NonNull String requestId;
  public final @NonNull String playerId;

  /**
   * Creates a completable request.
   *
   * @param playerId the player ID
   * @param request the original request
   */
  public RequestCompleter(
      final @NonNull String playerId,
      final @NonNull Request request
  ) {
    this.playerId = playerId;
    this.request = request;

    requestId = UUID.randomUUID().toString();
    future =  new CompletableFuture<Request>();
  }

  /**
   * Returns the type of the request.
   *
   * @return the type of the request.
   */
  @NonNull
  public ResourceType getType() {
    switch (request.type) {
      case Request.DATA_TYPE_DRM_PROVISION:
        return ResourceType.DRM_CERTIFICATE;
      case Request.DATA_TYPE_DRM_LICENSE:
        return ResourceType.DRM_LICENSE;
      default:
        return ResourceType.OTHER;
    }
  }

  @NonNull
  public Uri getUrl() {
    return request.getUri();
  }

  @NonNull
  public RequestMethod getMethod() {
    return RequestMethod.POST;
  }

  @NonNull
  public Map<String, String> getHeaders() {
    return request.headers;
  }

  @Nullable
  public byte[] getBody() {
    return request.getData();
  }

  public void setUrl(final @NonNull Uri url) {
    request.setUri(url);
  }

  public void setHeaders(
      final @NonNull Map<String, String> headers
  ) {
    request.headers.clear();
    request.headers.putAll(headers);
  }

  public void setBody(
      final @NonNull byte[] body
  ) {
    request.setData(body);
  }

  @NonNull
  public Future<Request> getCompleted() {
    return future;
  }

  public synchronized void complete() {
    future.complete(request);
  }
}
