package com.castlabs.reactnative.thumbnails;

import android.content.Context;
import android.graphics.Bitmap;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.castlabs.reactnative.errors.ErrorCode;
import com.castlabs.reactnative.errors.ErrorSeverity;
import com.castlabs.reactnative.errors.PrestoPlayError;
import com.castlabs.reactnative.player.Player;
import com.castlabs.sdk.thumbs.ThumbnailProvider;
import com.castlabs.sdk.thumbs.ThumbsPlugin;
import com.castlabs.reactnative.thumbnails.R;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * The view component for thumbnail.
 */
@RequiresApi(api = Build.VERSION_CODES.N)
public class ThumbnailView extends FrameLayout implements ThumbnailProvider.Callback {
  private static final String TAG = "ThumbnailView";

  private final Map<String, Player> playerInstanceManager;

  private String playerId;
  private Long positionMs;
  private final ImageView imageView;

  /**
   * Initializes the image view.
   *
   * @param context the application context
   * @param attrs the additional attributes
   * @param playerInstanceManager the global player provider map
   */
  public ThumbnailView(
      @NonNull Context context,
      @Nullable AttributeSet attrs,
      @NonNull Map<String, Player> playerInstanceManager
  ) {
    super(context, attrs);

    this.playerInstanceManager = playerInstanceManager;

    FrameLayout mainView = (FrameLayout) View.inflate(
        getContext(), R.layout.view_thumbnail, null);
    imageView = mainView.findViewById(R.id.thumbnailView);
    imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
    addView(mainView);
  }

  /**
   * Attaches a player to this thumbnail view.
   *
   * @param playerId the UUID of the player
   */
  public void setPlayerId(String playerId) {
    this.playerId = playerId;
    loadThumbnail();
  }

  /**
   * Sets an image to the thumbnail view according to the given position.
   *
   * @param positionMs the position in milliseconds
   */
  public void setPositionMs(double positionMs) {
    this.positionMs = (long) positionMs;
    loadThumbnail();
  }

  private void loadThumbnail() {
    if (playerId == null || positionMs == null) {
      return;
    }

    Player player = playerInstanceManager.get(playerId);
    if (player == null) {
      return;
    }

    ThumbnailProvider thumbnailProvider =
        player.getDelegate().getComponent(ThumbnailProvider.class);

    if (thumbnailProvider == null) {
      return;
    }

    thumbnailProvider.getThumbnail(
        TimeUnit.MILLISECONDS.toMicros(positionMs),
        this,
        ThumbsPlugin.THUMBNAIL_INDEX_CLOSEST
    );
  }

  @Override
  public void onThumbnailLoaded(
      long requestedPositionUs,
      long actualPositionUs,
      @Nullable Bitmap bitmap
  ) {
    if (bitmap != null) {
      imageView.setImageBitmap(bitmap);
    }
  }

  @Override
  public void onThumbnailLoadError(long l, @Nullable Exception e) {
    Log.e(TAG, "Failed to load thumbnail at position " + l, e);
    PrestoPlayError error = new PrestoPlayError(
      ErrorSeverity.RECOVERABLE,
      ErrorCode.THUMBNAILS_IMAGE_MISSING,
      "Failed to load thumbnail at position " + l,
      e!=null?e.toString():"",
      null,
      null);
    Player player = playerInstanceManager.get(playerId);
    player.emitError(error);
  }
}
