using System;
#if UNITY_WEBGL && !UNITY_EDITOR
using System.Runtime.InteropServices;
#endif

namespace BilibiliMiniGame
{
    internal sealed partial class BilibiliMiniGameBridge
    {
#if UNITY_WEBGL && !UNITY_EDITOR
        [DllImport("__Internal")]
        private static extern void BL_CheckScene(string scene, string receiverName, string requestId);

        [DllImport("__Internal")]
        private static extern void BL_NavigateToScene(string scene, string receiverName, string requestId);

        [DllImport("__Internal")]
        private static extern void BL_AddShortcut(string receiverName, string requestId);

        [DllImport("__Internal")]
        private static extern void BL_CheckShortcut(string receiverName, string requestId);

        [DllImport("__Internal")]
        private static extern void BL_RequestRecharge(
            string orderId,
            string payInfo,
            string devOrderId,
            string receiverName,
            string requestId);
#endif

        internal static BilibiliMiniGameRequest BL_CheckScene(
            BilibiliMiniGameSdk owner,
            string scene,
            float timeoutSeconds,
            Action<BilibiliMiniGameResponse> onSuccess,
            Action<BilibiliMiniGameError> onFail,
            Action onComplete)
        {
            PendingRequest request = BL_CreatePendingRequest(
                owner, timeoutSeconds, onSuccess, onFail, onComplete);
            BilibiliMiniGameBridge bridge = BL_GetOrCreate();
#if UNITY_WEBGL && !UNITY_EDITOR
            bridge.BL_RegisterAndInvoke(
                request,
                scene,
                () => BL_CheckScene(scene, BridgeObjectName, request.RequestId));
#else
            bridge.BL_RegisterAndInvoke(request, scene, null);
#endif
            return new BilibiliMiniGameRequest(request.RequestId);
        }

        internal static BilibiliMiniGameRequest BL_NavigateToScene(
            BilibiliMiniGameSdk owner,
            string scene,
            float timeoutSeconds,
            Action<BilibiliMiniGameResponse> onSuccess,
            Action<BilibiliMiniGameError> onFail,
            Action onComplete)
        {
            PendingRequest request = BL_CreatePendingRequest(
                owner, timeoutSeconds, onSuccess, onFail, onComplete);
            BilibiliMiniGameBridge bridge = BL_GetOrCreate();
#if UNITY_WEBGL && !UNITY_EDITOR
            bridge.BL_RegisterAndInvoke(
                request,
                scene,
                () => BL_NavigateToScene(scene, BridgeObjectName, request.RequestId));
#else
            bridge.BL_RegisterAndInvoke(request, scene, null);
#endif
            return new BilibiliMiniGameRequest(request.RequestId);
        }

        internal static BilibiliMiniGameRequest BL_AddShortcut(
            BilibiliMiniGameSdk owner,
            float timeoutSeconds,
            Action<BilibiliMiniGameResponse> onSuccess,
            Action<BilibiliMiniGameError> onFail,
            Action onComplete)
        {
            PendingRequest request = BL_CreatePendingRequest(
                owner, timeoutSeconds, onSuccess, onFail, onComplete);
            BilibiliMiniGameBridge bridge = BL_GetOrCreate();
#if UNITY_WEBGL && !UNITY_EDITOR
            bridge.BL_RegisterAndInvoke(
                request,
                () => BL_AddShortcut(BridgeObjectName, request.RequestId));
#else
            bridge.BL_RegisterAndInvoke(request, null);
#endif
            return new BilibiliMiniGameRequest(request.RequestId);
        }

        internal static BilibiliMiniGameRequest BL_CheckShortcut(
            BilibiliMiniGameSdk owner,
            float timeoutSeconds,
            Action<BilibiliMiniGameResponse> onSuccess,
            Action<BilibiliMiniGameError> onFail,
            Action onComplete)
        {
            PendingRequest request = BL_CreatePendingRequest(
                owner, timeoutSeconds, onSuccess, onFail, onComplete);
            BilibiliMiniGameBridge bridge = BL_GetOrCreate();
#if UNITY_WEBGL && !UNITY_EDITOR
            bridge.BL_RegisterAndInvoke(
                request,
                () => BL_CheckShortcut(BridgeObjectName, request.RequestId));
#else
            bridge.BL_RegisterAndInvoke(request, null);
#endif
            return new BilibiliMiniGameRequest(request.RequestId);
        }

        internal static BilibiliMiniGameRequest BL_RequestRecharge(
            BilibiliMiniGameSdk owner,
            string orderId,
            string payInfo,
            string devOrderId,
            float timeoutSeconds,
            Action<BilibiliMiniGameResponse> onSuccess,
            Action<BilibiliMiniGameError> onFail,
            Action onComplete)
        {
            PendingRequest request = BL_CreatePendingRequest(
                owner, timeoutSeconds, onSuccess, onFail, onComplete);
            BilibiliMiniGameBridge bridge = BL_GetOrCreate();
#if UNITY_WEBGL && !UNITY_EDITOR
            bridge.BL_RegisterAndInvoke(
                request,
                () => BL_RequestRecharge(
                    orderId ?? string.Empty,
                    payInfo ?? string.Empty,
                    devOrderId ?? string.Empty,
                    BridgeObjectName,
                    request.RequestId));
#else
            bridge.BL_RegisterAndInvoke(request, null);
#endif
            return new BilibiliMiniGameRequest(request.RequestId);
        }

        private static PendingRequest BL_CreatePendingRequest(
            BilibiliMiniGameSdk owner,
            float timeoutSeconds,
            Action<BilibiliMiniGameResponse> onSuccess,
            Action<BilibiliMiniGameError> onFail,
            Action onComplete)
        {
            return PendingRequest.BL_Create(
                owner,
                BL_CreateRequestId(),
                timeoutSeconds,
                onSuccess,
                onFail,
                onComplete);
        }
    }
}
