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

import static com.volcengine.velive.rn.pull.pictureInpicture.FloatingWindowService.INTENT_EXTRA_KEY_ASPECT_RATIO;
import static com.volcengine.velive.rn.pull.pictureInpicture.FloatingWindowService.INTENT_EXTRA_KEY_X_POS;
import static com.volcengine.velive.rn.pull.pictureInpicture.FloatingWindowService.INTENT_EXTRA_KEY_Y_POS;
import static com.volcengine.velive.rn.pull.pictureInpicture.IFloatingWindowHelper.Listener.ERR_INVALID_PARAMS;
import static com.volcengine.velive.rn.pull.pictureInpicture.IFloatingWindowHelper.Listener.ERR_IS_ALREADY_OPEN;
import static com.volcengine.velive.rn.pull.pictureInpicture.IFloatingWindowHelper.Listener.ERR_NO;
import static com.volcengine.velive.rn.pull.pictureInpicture.IFloatingWindowHelper.Listener.ERR_NOT_SUPPORT;
import static com.volcengine.velive.rn.pull.pictureInpicture.IFloatingWindowHelper.Listener.ERR_RETRY;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.view.SurfaceView;
import androidx.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;

public class FloatingWindowHelper implements IFloatingWindowHelper {
  private static FloatingWindowHelper mInstance = null;
  private Listener mListener;
  private Config mConfig;
  private Map<String, Object> mExtraDataMap;
  private boolean isRunning;

  public synchronized static FloatingWindowHelper getInstance() {
    if (mInstance == null) {
      mInstance = new FloatingWindowHelper();
    }
    return mInstance;
  }

  public static boolean isPictureInPictureSupported() {
    // Check if the system version supports floating windows
    if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.M) {
      // Android versions below 6.0 don't support SYSTEM_ALERT_WINDOW permission
      // management
      return false;
    }
    // The system supports PIP mode
    return true;
  }

  @Override
  public void setEventListener(Listener listener) {
    mListener = listener;
  }

  public Listener getEventListener() { return mListener; }

  public void openFloatingWindow(Context context, Config config,
                                 Map<String, Object> extraData) {
    if (isRunning) {
      if (mListener != null) {
        mListener.onOpenFloatingWindowResult(ERR_IS_ALREADY_OPEN, extraData);
      }
      return;
    }
    // Invalid parameters
    if (context == null || config.aspectRatio <= 0) {
      if (mListener != null) {
        mListener.onOpenFloatingWindowResult(ERR_INVALID_PARAMS, extraData);
      }
      return;
    }

    // Android versions below 6.0 don't support Overlay functionality
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
      if (mListener != null) {
        mListener.onOpenFloatingWindowResult(ERR_NOT_SUPPORT, extraData);
      }
      return;
    }

    // Save configuration first, so it can be used in permission request
    // callback
    mConfig = config;
    mExtraDataMap = extraData;

    // If Overlay permission is not enabled, request it first
    if (!Settings.canDrawOverlays(context)) {
      if (mListener != null && mListener.onRequestOverlayPermission()) {
        requestOverlayPermission(context);
      } else {
        // User doesn't allow permission request, trigger error callback
        if (mListener != null) {
          mListener.onOpenFloatingWindowResult(ERR_INVALID_PARAMS, extraData);
        }
      }
      return;
    }

    Intent intent = new Intent(context, FloatingWindowService.class);
    intent.putExtra(INTENT_EXTRA_KEY_ASPECT_RATIO, mConfig.aspectRatio);
    intent.putExtra(INTENT_EXTRA_KEY_X_POS, mConfig.x);
    intent.putExtra(INTENT_EXTRA_KEY_Y_POS, mConfig.y);
    context.startService(intent);
    isRunning = true;
  }

  @Override
  public void closeFloatingWindow(Context context) {
    if (!isRunning) {
      return;
    }
    context.stopService(new Intent(context, FloatingWindowService.class));
    isRunning = false;
  }

  @Override
  public void requestOverlayPermission(Context context) {
    try {
      Intent intent = new Intent(context, AssistantActivity.class);
      intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      context.startActivity(intent);
    } catch (Exception e) {
      // If starting AssistantActivity fails, trigger error callback
      if (mListener != null) {
        Map<String, Object> errorData = new HashMap<>();
        errorData.put("error", e.getMessage());
        mListener.onOpenFloatingWindowResult(ERR_NOT_SUPPORT, errorData);
      }
    }
  }

  @Override
  public Config getConfig() {
    return mConfig;
  }

  @Override
  public Map<String, Object> getExtraData() {
    return mExtraDataMap;
  }

  @Override
  public boolean isOpen() {
    return isRunning;
  }

  void setSurfaceView(SurfaceView surfaceView) {
    if (mListener != null) {
      mListener.onUpdateSurfaceView(surfaceView);
    }
  }

  void onClickFloatingWindowCloseBtn(Context context) {
    if (mListener != null) {
      mListener.onClickFloatingWindowCloseBtn(context);
    }
  }

  void onClickFloatingWindow(Context context) {
    if (mListener != null) {
      mListener.onClickFloatingWindow(context);
    }
  }

  void onStartService() {
    if (mListener != null) {
      mListener.onOpenFloatingWindowResult(ERR_NO, mExtraDataMap);
    }
  }

  void onStopService() {
    if (mListener != null) {
      mListener.onCloseFloatingWindow(mExtraDataMap);
    }

    mConfig = null;
    mExtraDataMap = null;
    isRunning = false;
  }

  public static class AssistantActivity extends Activity {
    private Listener mListener;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      mListener = FloatingWindowHelper.getInstance().getEventListener();

      int sdkInt = Build.VERSION.SDK_INT;
      int mOverlayRequestCode = 1001;
      if (sdkInt >= Build.VERSION_CODES.O) { // Android 8.0 and above
        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
        startActivityForResult(intent, mOverlayRequestCode);
      } else if (sdkInt >= Build.VERSION_CODES.M) {
        Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
        intent.setData(Uri.parse("package:" + getPackageName()));
        startActivityForResult(intent, mOverlayRequestCode);
      }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode,
                                    @Nullable Intent data) {
      super.onActivityResult(requestCode, resultCode, data);

      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (!Settings.canDrawOverlays(this)) {
          // User denied permission request, return permission error
          if (mListener != null) {
            mListener.onOpenFloatingWindowResult(ERR_INVALID_PARAMS, null);
          }
        } else {
          // User granted permission
          if (mListener != null) {
            // Return success directly, let the caller retry
            // startPictureInPicture
            mListener.onOpenFloatingWindowResult(ERR_RETRY, null);
          }
        }
      }

      // Finish activity regardless of the result
      finish();
    }
  }
}
