package com.castlabs.reactnative.network;

import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import com.castlabs.android.network.Response;
import com.castlabs.android.network.ResponseModifier;
import com.castlabs.reactnative.utils.DrmEventEmitter;

import java.util.Map;
import java.util.concurrent.ExecutionException;

/**
 * The asynchronous response modifier.
 */
@RequiresApi(api = Build.VERSION_CODES.N)
public class DeferredResponseModifier implements ResponseModifier {
  private final @NonNull DrmEventEmitter drmEventEmitter;
  private final @NonNull Map<String, ResponseCompleter> responseCompleterCache;
  private final @NonNull String playerId;

  /**
   * Creates the response modifier.
   *
   * @param drmEventEmitter the global event emitter
   * @param responseCompleterCache the global response completer cache
   * @param playerId the player ID
   */
  public DeferredResponseModifier(
      @NonNull final DrmEventEmitter drmEventEmitter,
      @NonNull final Map<String, ResponseCompleter> responseCompleterCache,
      @NonNull final String playerId
  ) {
    this.drmEventEmitter = drmEventEmitter;
    this.responseCompleterCache = responseCompleterCache;
    this.playerId = playerId;
  }

  /**
   * Triggered on a new response.
   *
   * @param response the original response
   * @return the modified response
   */
  @NonNull
  @Override
  public Response onResponse(@NonNull final Response response) {
    if (response.type != Response.DATA_TYPE_DRM_LICENSE
        && response.type != Response.DATA_TYPE_DRM_PROVISION) {
      return response;
    }

    if ("www.googleapis.com".equals(response.uri.getHost())) {
      // ignore requests to Google API, for example:
      // https://www.googleapis.com/certificateprovisioning
      return response;
    }

    final ResponseCompleter responseCompleter = new ResponseCompleter(playerId, response);
    responseCompleterCache.put(responseCompleter.responseId, responseCompleter);

    drmEventEmitter.emitNewResponse(
        playerId,
        responseCompleter.responseId,
        responseCompleter.getType(),
        responseCompleter.getStatus(),
        responseCompleter.getUrl(),
        responseCompleter.getHeaders(),
        responseCompleter.getBody()
    );

    try {
      return responseCompleter.getCompleted().get();
    } catch (ExecutionException | InterruptedException e) {
      throw new RuntimeException(e);
    }
  }
}
