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

namespace Arkadium
{
	[Serializable]
	public class UserProfileImage {
		public string png;
		public string webp;
	}

	[Serializable]
	public class UserProfile {
		public string uid;
		public string username;
		public UserProfileImage avatar;
		public UserProfileImage avatarFrame;
		public string avatarBackground;
		public bool isUserSubscriber;
	}

	public interface IArkadiumAuth
	{
		bool IsUserLoggedIn { get; }

		void IsUserAuthorized(Action<bool> cb);
		void SubscribeToAuthStatus(Action<bool> cb);
		void GetUserProfile(Action<UserProfile> cb);
		void OpenAuthForm(Action cb);
	}

	public class ArkadiumAuth : IArkadiumAuth
	{
	#if UNITY_WEBGL && !UNITY_EDITOR
		[DllImport("__Internal")]
		private static extern void _IsUserAuthorized(Action<int> cb);
		[DllImport("__Internal")]
		private static extern void _SubscribeToAuthStatus(Action<int> cb);
		[DllImport("__Internal")]
		private static extern void _GetUserProfile(Action<string> cb);
		[DllImport("__Internal")]
		private static extern void _OpenAuthForm(Action cb);
	#else
		private void _IsUserAuthorized(Action<int> cb) { cb?.Invoke(0); }
		private void _SubscribeToAuthStatus(Action<int> cb) { cb?.Invoke(0); }
		private void _GetUserProfile(Action<string> cb) { cb?.Invoke(""); }
		private void _OpenAuthForm(Action cb) { cb?.Invoke(); }
	#endif

		private static Action<bool> _isUserAuthorizedCb;
		private static event Action<bool> _subscribeToAuthStatusCb;
		private static Action<UserProfile> _getUserProfileCb;
		private static Action _openAuthFormCb;
		
		public bool IsUserLoggedIn { get; internal set; }

		public void IsUserAuthorized(Action<bool> cb) {
			_isUserAuthorizedCb = cb;
			_IsUserAuthorized(_IsUserAuthorizedCb);
		}

		public void SubscribeToAuthStatus(Action<bool> cb) {
			_subscribeToAuthStatusCb += cb;
			_SubscribeToAuthStatus(SubscribeToAuthStatusCb);
		}

		public void UnsubscribeToAuthStatus(Action<bool> cb) {
			_subscribeToAuthStatusCb -= cb;
		}

		public void GetUserProfile(Action<UserProfile> cb) {
			_getUserProfileCb = cb;
			_GetUserProfile(GetUserProfileCb);
		}
		
		public void OpenAuthForm(Action cb) {
			_openAuthFormCb = cb;
			_OpenAuthForm(OpenAuthFormCb);
		}
		
		[MonoPInvokeCallback(typeof(Action<int>))]
		private static void _IsUserAuthorizedCb(int result) {
			ArkadiumSDK.Instance.Log($"Get user authorized state returned {result}");
			_isUserAuthorizedCb?.Invoke(result == 1);
			_isUserAuthorizedCb = null;
		}

		[MonoPInvokeCallback(typeof(Action<int>))]
		private static void SubscribeToAuthStatusCb(int signedIn) {
			ArkadiumSDK.Instance.Log($"Subscribe to auth status returned {signedIn}");
			var isSignedIn = signedIn == 1;
			ArkadiumSDK.Instance.Auth.IsUserLoggedIn = isSignedIn;
			_subscribeToAuthStatusCb?.Invoke(isSignedIn);
		}

		[MonoPInvokeCallback(typeof(Action<string>))]
		private static void GetUserProfileCb(string profileSerialized) {
			ArkadiumSDK.Instance.Log($"Get user profile returned {profileSerialized}");
			if (string.IsNullOrEmpty(profileSerialized)) {
				_getUserProfileCb?.Invoke(null);
				_getUserProfileCb = null;
				return;
			}
			try {
				var profile = JsonUtility.FromJson<UserProfile>(profileSerialized);
				_getUserProfileCb?.Invoke(profile);
				_getUserProfileCb = null;
			} catch (Exception) {}
		}

		[MonoPInvokeCallback(typeof(Action))]
		private static void OpenAuthFormCb() {
			ArkadiumSDK.Instance.Log("Auth form opened");
			_openAuthFormCb?.Invoke();
			_openAuthFormCb = null;
		}
	}
}