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

namespace Arkadium
{
	[Flags]
	public enum LogLevel
	{
		NONE = 0,
		UNITY_LOGS = 1,
		JSLIB_LOGS = 2,
		ALL_LOGS = 3
	}

	public interface IArkadiumSDK
	{
		ArkadiumAds Ads { get; }
		ArkadiumAnalytics Analytics { get; }
		ArkadiumAuth Auth { get; }
		ArkadiumHost Host { get; }
		ArkadiumLifecycle Lifecycle { get; }
		ArkadiumPersistence Persistence { get; }
		ArkadiumWalletV2 Wallet { get; }
		ArkadiumLeaderboard Leaderboard { get; }
		ArkadiumTournaments Tournaments { get; }

		bool IsInitialized { get; }

		void SetLogLevel(LogLevel logLevel);
		void InitializeDev(string eagleGameSlug, Action<bool> cb);
		void Initialize(string eagleGameSlug, Action<bool> cb);
		void InitializeWithUrlParam(string eagleGameSlug, Action<bool> cb);
	}

	public class ArkadiumSDK : IArkadiumSDK
	{

#if UNITY_WEBGL && !UNITY_EDITOR
		[DllImport("__Internal")]
		private static extern void _Initialize(string environment, string gameObjectName, Action<int> cb);
		[DllImport("__Internal")]
		private static extern void _LogState(bool state);
#else
		private void _Initialize(string environment, string gameObjectName, Action<int> cb) { cb?.Invoke(0); }
		private void _LogState(bool state) { }
#endif

		private static Action<bool> _initializeCb;
		private static ArkadiumSDK _instance;

		private LogLevel _logLevel;

		public static ArkadiumSDK Instance => _instance ??= new ArkadiumSDK();

		public ArkadiumAds Ads { get; }
		public ArkadiumAnalytics Analytics { get; }
		public ArkadiumAuth Auth { get; }
		public ArkadiumHost Host { get; }
		public ArkadiumLifecycle Lifecycle { get; }
		public ArkadiumPersistence Persistence { get; }
		public ArkadiumWalletV2 Wallet { get; }
		public ArkadiumLeaderboard Leaderboard { get; }
		public ArkadiumTournaments Tournaments { get; }

		public bool IsInitialized { get; internal set; }

		public ArkadiumSDK()
		{
			SetLogLevel(LogLevel.ALL_LOGS);

			Ads = new ArkadiumAds();
			Analytics = new ArkadiumAnalytics();
			Auth = new ArkadiumAuth();
			Host = new ArkadiumHost();
			Lifecycle = new ArkadiumLifecycle();
			Persistence = new ArkadiumPersistence();
			Wallet = new ArkadiumWalletV2();
			Leaderboard = new ArkadiumLeaderboard();
			Tournaments = new ArkadiumTournaments();
			_instance ??= this;
		}

		public void SetLogLevel(LogLevel logLevel)
		{
			_logLevel = logLevel;

			_LogState((_logLevel & LogLevel.JSLIB_LOGS) != 0);
		}

		public void InitializeDev(string eagleGameSlug, Action<bool> cb)
		{
			_initializeCb = cb;
			_Initialize("DEV", eagleGameSlug, InitializeCb);
		}

		public void Initialize(string eagleGameSlug, Action<bool> cb)
		{
			_initializeCb = cb;
			_Initialize("PROD", eagleGameSlug, InitializeCb);
		}

		public void InitializeWithUrlParam(string eagleGameSlug, Action<bool> cb)
		{
			_initializeCb = cb;
			_Initialize("URL", eagleGameSlug, InitializeCb);
		}

		[MonoPInvokeCallback(typeof(Action<int>))]
		private static void InitializeCb(int success)
		{
			var isInitialized = success == 1;

			_instance.IsInitialized = isInitialized;

			_initializeCb?.Invoke(isInitialized);
			_initializeCb = null;

			if (isInitialized)
			{
				_instance.Auth.SubscribeToAuthStatus(null);
			}

			_instance.Log($"initialize returned {isInitialized}");
		}

		internal void Log(string message)
		{
			if ((_logLevel & LogLevel.UNITY_LOGS) != 0)
			{
				Debug.Log($"[Arkadium SDK Unity] - {message}");
			}
		}
	}
}

