package com.volcengine.velive.rn.pull.pictureInpicture;

import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.SurfaceView;
import com.ss.videoarch.liveplayer.VeLivePlayer;
import java.util.HashMap;
import java.util.Map;

/**
 * Manager class that provides easy access to Picture-in-Picture functionality
 * for React Native code.
 */
public class PictureInPictureManager {
  private static final String TAG = "PipManager";
  private static PictureInPictureManager sInstance;
  private final FloatingWindowHelper mFloatingWindowHelper;

  private Context mContext;
  private SurfaceView mSurfaceView;
  private VeLivePlayer mPlayer;
  // Flag indicating whether we're in the process of switching to PIP mode
  // Used to control SurfaceView switching state
  private boolean mSwitchingToPip = false;
  private IFloatingWindowHelper.Config mConfig =
      new IFloatingWindowHelper.Config(16f / 9f, 0, 0);
  private Listener mListener;

  private PictureInPictureManager() {
    mFloatingWindowHelper = FloatingWindowHelper.getInstance();
    setupFloatingWindowListener();
  }

  public static synchronized PictureInPictureManager getInstance() {
    if (sInstance == null) {
      sInstance = new PictureInPictureManager();
    }
    return sInstance;
  }

  /**
   * Set the player instance to be managed
   */
  public void setupPlayer(VeLivePlayer player, Context context,
                          SurfaceView surfaceView) {
    mPlayer = player;
    mContext = context;
    mSurfaceView = surfaceView;

    // Register player with reference manager
    if (player instanceof VeLiveRefManager.IObject) {
      VeLiveRefManager.addRef((VeLiveRefManager.IObject)player);
    }
  }

  public void setupConfig(float aspectRatio, int x, int y) {
    mConfig = new IFloatingWindowHelper.Config(aspectRatio, x, y);
  }

  /**
   * Check if the device supports picture-in-picture
   * @return true if supported and has permission, false otherwise
   */
  public boolean isPictureInPictureSupported() {
    return FloatingWindowHelper.isPictureInPictureSupported();
  }

  public boolean startPictureInPicture() {
    return startPictureInPicture(mConfig);
  }

  public boolean startPictureInPicture(float aspectRatio, int x, int y) {
    mConfig = new IFloatingWindowHelper.Config(aspectRatio, x, y);
    return startPictureInPicture(mConfig);
  }

  /**
   * Start picture-in-picture mode
   * @return true if PIP was started, false otherwise
   */
  public boolean startPictureInPicture(IFloatingWindowHelper.Config config) {
    Log.d(TAG, "Starting picture-in-picture mode");
    if (mPlayer == null) {
      Log.e(TAG, "Cannot start PIP: player is null");
      return false;
    }

    if (mFloatingWindowHelper.isOpen()) {
      Log.d(TAG, "PIP already active");
      return true;
    }

    // Check overlay permissions
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M &&
        !android.provider.Settings.canDrawOverlays(mContext)) {
      Log.d(TAG, "Requesting overlay permission");
      mFloatingWindowHelper.requestOverlayPermission(mContext);
      return false;
    }

    // Mark that we're switching to PIP mode
    // This flag will be used in onUpdateSurfaceView callback
    mSwitchingToPip = true;

    // Default empty data
    Map<String, Object> extraData = new HashMap<>();

    // Call FloatingWindowHelper to open the floating window
    mFloatingWindowHelper.openFloatingWindow(mContext, config, extraData);
    return true;
  }

  /**
   * Stop picture-in-picture mode
   */
  public void stopPictureInPicture() {
    Log.d(TAG, "Stopping picture-in-picture mode");

    // Ensure the floating window is closed
    if (mFloatingWindowHelper.isOpen() && mContext != null) {
      mFloatingWindowHelper.closeFloatingWindow(mContext);
    }

    // Reset the state flag regardless of whether the window was closed
    // successfully
    mSwitchingToPip = false;
  }

  /**
   * Check if picture-in-picture is active
   *
   * @return true if PIP is active, false otherwise
   */
  public boolean isPictureInPictureActive() {
    return mFloatingWindowHelper.isOpen();
  }

  /**
   * Request overlay permission if needed
   *
   * @param context Android context
   */
  public void requestOverlayPermission(Context context) {
    mFloatingWindowHelper.requestOverlayPermission(context);
  }

  /**
   * Set up floating window listener
   */
  private void setupFloatingWindowListener() {
    mFloatingWindowHelper.setEventListener(
        new IFloatingWindowHelper.Listener() {
          @Override
          public void onOpenFloatingWindowResult(
              int errCode, Map<String, Object> extraData) {
            if (errCode == ERR_RETRY) {
              // Retry
              startPictureInPicture(mConfig);
              return;
            }
            if (mListener != null) {
              if (errCode == ERR_NO) {
                mListener.onStartPictureInPicture();
              } else {
                mListener.onError(errCode, extraData);
              }
            }
            Log.d(TAG, "PIP window opened");
          }

          @Override
          public void onUpdateSurfaceView(SurfaceView surfaceView) {
            Log.d(TAG, "onUpdateSurfaceView called with new SurfaceView");
            if (mSwitchingToPip && mPlayer != null && surfaceView != null) {
              Log.d(TAG, "Switching player to PIP surface");
              // Switch player to the SurfaceView provided by
              // FloatingWindowService
              mPlayer.setSurfaceHolder(surfaceView.getHolder());
              // Reset the flag after switching is complete
              mSwitchingToPip = false;
            }
          }

          @Override
          public void onClickFloatingWindow(Context context) {
            if (mListener != null) {
              mListener.onClickPictureInPicture();
            }
          }

          @Override
          public void onClickFloatingWindowCloseBtn(Context context) {
            Log.d(TAG, "PIP close button clicked");
            mFloatingWindowHelper.closeFloatingWindow(context);
            if (mPlayer != null) {
              mPlayer.pause();
            }
          }

          @Override
          public void onCloseFloatingWindow(Map<String, Object> extraData) {
            if (mListener != null) {
              mListener.onStopPictureInPicture();
            }
            Log.d(TAG, "PIP window closed");
            // Ensure we're completely out of PIP mode
            mSwitchingToPip = false;
            if (mPlayer != null && mSurfaceView != null) {
              Log.d(TAG, "Switching player back to original surface");
              mPlayer.setSurfaceHolder(mSurfaceView.getHolder());
            }

            // Release player reference when closing
            if (mPlayer instanceof VeLiveRefManager.IObject) {
              VeLiveRefManager.decRef((VeLiveRefManager.IObject)mPlayer);
            }
          }
        });
  }

  public void setListener(Listener listener) { mListener = listener; }

  public interface Listener {
    /**
     * Callback when picture-in-picture mode starts
     * Default empty implementation, subclasses can override as needed
     */
    public default void onStartPictureInPicture() {
      // Empty implementation, subclasses can override as needed
    }

    /**
     * Callback when picture-in-picture mode stops
     * Default empty implementation, subclasses can override as needed
     */
    public default void onStopPictureInPicture() {
      // Empty implementation, subclasses can override as needed
    }

    /**
     * Callback when the picture-in-picture window is clicked
     * Default empty implementation, subclasses can override as needed
     */
    public default void onClickPictureInPicture() {
      // Empty implementation, subclasses can override as needed
    }

    /**
     * Error callback
     * @param errCode Error code, 0 means success, other values indicate errors
     * @param extraData Additional data, can be used to pass error information
     * Default empty implementation, subclasses can override as needed
     */
    public default void onError(int errCode, Map<String, Object> extraData) {
      // Empty implementation, subclasses can override as needed
    }
  }
  ;
}