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

import android.util.Log;
import java.util.HashMap;
import java.util.Map;

/**
 * Player reference count manager
 * Used to share player instances between Activity and floating window
 */
public class VeLiveRefManager {
  private static final String TAG = "VeLiveRefManager";
  private static final VeLiveRefManager INSTANCE = new VeLiveRefManager();

  /**
   * Interface for objects that can be reference-counted
   */
  public interface IObject {
    /**
     * Get the unique identifier for the object, defaults to the object itself
     */
    default Object getId() { return this; }

    /**
     * Callback triggered when reference count drops to zero
     */
    void onDecRef();
  }

  private static final Map<Object, Integer> mRefMap = new HashMap<>();

  private VeLiveRefManager() {
    // Private constructor to ensure singleton pattern
  }

  public static VeLiveRefManager getInstance() { return INSTANCE; }

  /**
   * Increase the reference count for an object
   * @param object The object to increase reference count for
   */
  public synchronized static void addRef(IObject object) {
    if (object == null) {
      Log.d(TAG, "addRef: object is null");
      return;
    }

    Object id = object.getId();
    int refCnt = 1;
    if (mRefMap.containsKey(id)) {
      refCnt += mRefMap.get(id);
    }
    mRefMap.put(id, refCnt);
    Log.d(TAG, "addRef: object=" + id + ", new refCnt=" + refCnt);
  }

  /**
   * Decrease the reference count for an object
   * When the count reaches zero, the object's onDecRef method will be called
   * @param object The object to decrease reference count for
   */
  public synchronized static void decRef(IObject object) {
    if (object == null) {
      Log.d(TAG, "decRef: object is null");
      return;
    }

    Object id = object.getId();
    if (!mRefMap.containsKey(id)) {
      Log.d(TAG, "decRef: object=" + id + " not found in refMap");
      return;
    }

    int refCnt = mRefMap.get(id) - 1;
    Log.d(TAG, "decRef: object=" + id + ", new refCnt=" + refCnt);

    if (refCnt <= 0) {
      mRefMap.remove(id);
      Log.d(TAG,
            "decRef: object=" + id + " removed from refMap, calling onDecRef");
      object.onDecRef();
    } else {
      mRefMap.put(id, refCnt);
    }
  }

  /**
   * Get the current reference count for an object
   * @param object The object to query
   * @return The reference count, or 0 if the object doesn't exist
   */
  public synchronized int getRefCount(IObject object) {
    if (object == null) {
      return 0;
    }

    Object id = object.getId();
    if (!mRefMap.containsKey(id)) {
      return 0;
    }

    return mRefMap.get(id);
  }

  /**
   * Clear all reference count records
   * Note: This will call onDecRef for all objects
   */
  public synchronized void clearAll() {
    Log.d(TAG, "clearAll: clearing all references");
    for (Map.Entry<Object, Integer> entry : mRefMap.entrySet()) {
      if (entry.getKey() instanceof IObject) {
        Log.d(TAG, "clearAll: calling onDecRef for object=" + entry.getKey());
        ((IObject)entry.getKey()).onDecRef();
      }
    }
    mRefMap.clear();
  }
}