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

namespace Arkadium
{
	public interface IArkadiumLeaderboard
	{

		void IsSupported(Action<bool> cb);
		void PostScore(int score, Action<bool> cb);
		void GetUserScore(Action<int> cb, string type = "");
		void GetTopScores(Action<LeaderboardEntry[]> cb, string type = "", int limit = 100);
	}

	public class LeaderboardEntry
	{
		public int rank { get; set; }
		public int score { get; set; }
		public string username { get; set; }
		public string avatar { get; set; }

		public override string ToString()
		{
			return "LeaderboardEntry: rank: " + rank + ", score: " + score + ", username: " + username + ", avatar: " + avatar;
		}
	}

	public class ArkadiumLeaderboard : IArkadiumLeaderboard
	{
#if UNITY_WEBGL && !UNITY_EDITOR
		[DllImport("__Internal")]
		private static extern void _LeaderboardIsSupported(Action<int> cb);
		[DllImport("__Internal")]
		private static extern void _LeaderboardPostScore(int score, Action<int> cb);
		[DllImport("__Internal")]
		private static extern void _LeaderboardGetUserScore(Action<int> cb, string type);
		[DllImport("__Internal")]
		private static extern void _LeaderboardGetTopScores(Action<string> cb, string type, int limit);
#else
		private void _LeaderboardIsSupported(Action<int> cb) { cb?.Invoke(1); }
		private void _LeaderboardPostScore(int score, Action<int> cb) { cb?.Invoke(1); }
		private void _LeaderboardGetUserScore(Action<int> cb, string type) { cb?.Invoke(10); }
		private void _LeaderboardGetTopScores(Action<string> cb, string type, int limit)
		{
			cb?.Invoke("[{\"rank\":1,\"score\":10,\"username\":\"testuser\",\"avatar\":\"avatar.png\"}]");
		}
#endif

		private static Action<bool> _isSupportedCb;
		private static Action<bool> _postScoreCb;
		private static Action<int> _getUserScoreCb;
		private static Action<LeaderboardEntry[]> _getTopScoresCb;

		// Is Supported
		public void IsSupported(Action<bool> cb)
		{
			_isSupportedCb = cb;
			_LeaderboardIsSupported(IsSupportedCb);
		}

		[MonoPInvokeCallback(typeof(Action<int>))]
		private static void IsSupportedCb(int result)
		{
			var success = result == 1;
			ArkadiumSDK.Instance.Log($"Leaderboard is supported: {success}");
			_isSupportedCb?.Invoke(success);
			_isSupportedCb = null;
		}

		// Post Score
		public void PostScore(int score, Action<bool> cb)
		{
			_postScoreCb = cb;
			_LeaderboardPostScore(score, PostScoreCb);
		}

		[MonoPInvokeCallback(typeof(Action<int>))]
		private static void PostScoreCb(int result)
		{
			var success = result == 1;
			ArkadiumSDK.Instance.Log($"Leaderboard post score: {success}");
			_postScoreCb?.Invoke(success);
			_postScoreCb = null;
		}

		// Get User Score
		public void GetUserScore(Action<int> cb, string type = "")
		{
			_getUserScoreCb = cb;
			_LeaderboardGetUserScore(GetUserScoreCb, type);
		}

		[MonoPInvokeCallback(typeof(Action<int>))]
		private static void GetUserScoreCb(int result)
		{
			ArkadiumSDK.Instance.Log($"Leaderboard get user score: {result}");
			_getUserScoreCb?.Invoke(result);
			_getUserScoreCb = null;
		}

		// Get Top Scores
		public void GetTopScores(Action<LeaderboardEntry[]> cb, string type = "", int limit = 100)
		{
			_getTopScoresCb = cb;
			_LeaderboardGetTopScores(GetTopScoresCb, type, limit);
		}

		[MonoPInvokeCallback(typeof(Action<string>))]
		private static void GetTopScoresCb(string json)
		{
			var entries = JsonConvert.DeserializeObject<LeaderboardEntry[]>(json);
			ArkadiumSDK.Instance.Log($"Leaderboard get top scores:");
			foreach (var item in entries)
			{
				ArkadiumSDK.Instance.Log($"{item.ToString()}");
			}
			_getTopScoresCb?.Invoke(entries);
			_getTopScoresCb = null;
		}
	}
}