//#define ENABLE_LOG
/*
 * Copyright (c) 2014 - 2022 t_saki@serenegiant.com 
 */

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using UnityEngine;

#if UNITY_ANDROID
#if UNITY_2018_3_OR_NEWER
using UnityEngine.Android;
#endif
#endif

namespace Serenegiant
{

	public class AndroidUtils : MonoBehaviour
	{
		public const string FQCN_UNITY_PLAYER = "com.unity3d.player.UnityPlayer";
		public const string PERMISSION_CAMERA = "android.permission.CAMERA";

		public enum PermissionGrantResult
		{
			PERMISSION_GRANT = 0,
			PERMISSION_DENY = -1,
			PERMISSION_DENY_AND_NEVER_ASK_AGAIN = -2
		}

		private const string TAG = "AndroidUtils#";
		private const string FQCN_PLUGIN = "com.serenegiant.androidutils.AndroidUtils";

		//--------------------------------------------------------------------------------
		/**
		 * 生命周期事件的交付者
		 * @param resumed true: onResume, false: onPause
		 */
		public delegate void LifecycleEventHandler(bool resumed);

		/***
		 * GrantPermission请求权限时的回调用delegateer
		 * @param permission
		 * @param grantResult 0:grant, -1:deny, -2:denyAndNeverAskAgain
		*/
		public delegate void OnPermission(string permission, PermissionGrantResult result);

		//--------------------------------------------------------------------------------
		/**
		 * 请求权限时超时
		 */
		public static float PermissionTimeoutSecs = 30;
	
		public event LifecycleEventHandler LifecycleEvent;

		public static bool isPermissionRequesting;
		private static PermissionGrantResult grantResult;

		void Awake()
		{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
			Console.WriteLine($"{TAG}Awake:");
#endif
#if UNITY_ANDROID
			Input.backButtonLeavesApp = true;   // 用终端的背键可以结束应用程序
			Initialize();
#endif
		}

		//--------------------------------------------------------------------------------
		// Java端的事件回调

		/**
		 * onStart事件
		 */
		public void OnStartEvent()
		{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
			Console.WriteLine($"{TAG}OnStartEvent:");
#endif
		}

		/**
		 * onResume事件
		 */
		public void OnResumeEvent()
		{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
			Console.WriteLine($"{TAG}OnResumeEvent:");
#endif
			LifecycleEvent?.Invoke(true);
		}

		/**
		 * onPause事件
		 */
		public void OnPauseEvent()
		{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
			Console.WriteLine($"{TAG}OnPauseEvent:");
#endif
			LifecycleEvent?.Invoke(false);
		}

		/**
		 * onStop事件
		 */
		public void OnStopEvent()
		{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
			Console.WriteLine($"{TAG}OnStopEvent:");
#endif
		}

		/**
		 * 已获得权限
		 */
		public void OnPermissionGrant()
		{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
			Console.WriteLine($"{TAG}OnPermissionGrant:");
#endif
			grantResult = PermissionGrantResult.PERMISSION_GRANT;
			isPermissionRequesting = false;
		}

		/**
		 * 无法获得权限
		 */
		public void OnPermissionDeny()
		{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
			Console.WriteLine($"{TAG}OnPermissionDeny:");
#endif
			grantResult = PermissionGrantResult.PERMISSION_DENY;
			isPermissionRequesting = false;
		}

		/**
		 * 设置为无法获取权限而不重新显示权限对话框
		 */
		public void OnPermissionDenyAndNeverAskAgain()
		{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
			Console.WriteLine($"{TAG}OnPermissionDenyAndNeverAskAgain:");
#endif
			grantResult = PermissionGrantResult.PERMISSION_DENY_AND_NEVER_ASK_AGAIN;
			isPermissionRequesting = false;
		}

		//--------------------------------------------------------------------------------
#if UNITY_ANDROID
		/**
		 * 初始化插件
		 */
		private void Initialize()
		{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
			Console.WriteLine($"{TAG}Initialize:{gameObject.name}");
#endif
			using (AndroidJavaClass clazz = new AndroidJavaClass(FQCN_PLUGIN))
			{
				clazz.CallStatic("initialize",
					AndroidUtils.GetCurrentActivity(), gameObject.name);
			}
		}

		/**
		 * 获取是否保留指定权限
		 * @param permission
		 * @param 指定已保留的权限
		 */
		public static bool HasPermission(string permission)
		{
			using (AndroidJavaClass clazz = new AndroidJavaClass(FQCN_PLUGIN))
			{
				return clazz.CallStatic<bool>("hasPermission",
					AndroidUtils.GetCurrentActivity(), permission);
			}
		}

		/**
		 * 获取是否需要查看指定权限的说明
		 * @param permission
		 * @param 必须显示指定权限的说明
		 */
		public static bool ShouldShowRequestPermissionRationale(string permission)
		{
			using (AndroidJavaClass clazz = new AndroidJavaClass(FQCN_PLUGIN))
			{
				return clazz.CallStatic<bool>("shouldShowRequestPermissionRationale",
					AndroidUtils.GetCurrentActivity(), permission);
			}
		}

		/**
		 * 权限要求
		 * 这是Java方面不进行Rationale的处理等
		 * @param permission
		 * @param callback
		 */
		public static IEnumerator RequestPermission(string permission, OnPermission callback)
		{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
			Console.WriteLine($"{TAG}GrantPermission:{permission}");
#endif
			if (!HasPermission(permission))
			{
				grantResult = PermissionGrantResult.PERMISSION_DENY;
				isPermissionRequesting = true;
				using (AndroidJavaClass clazz = new AndroidJavaClass(FQCN_PLUGIN))
				{
					clazz.CallStatic("requestPermission",
						AndroidUtils.GetCurrentActivity(), permission);
				}
				float timeElapsed = 0;
				while (isPermissionRequesting)
				{
					if ((PermissionTimeoutSecs > 0) && (timeElapsed > PermissionTimeoutSecs))
					{
						isPermissionRequesting = false;
						yield break;
					}
					timeElapsed += Time.deltaTime;
					yield return null;
				}
				callback(permission, grantResult);
			}
			else
			{
				callback(permission, PermissionGrantResult.PERMISSION_GRANT);
			}
	
			yield break;
		}

		/**
		 * 权限要求
		 * 这是在Java侧进行Rationale处理等
		 * @param permission
		 * @param callback
		 */
		public static IEnumerator GrantPermission(string permission, OnPermission callback)
		{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
			Console.WriteLine($"{TAG}GrantPermission:{permission}");
#endif
			if (!HasPermission(permission))
			{
				grantResult = PermissionGrantResult.PERMISSION_DENY;
				isPermissionRequesting = true;
				using (AndroidJavaClass clazz = new AndroidJavaClass(FQCN_PLUGIN))
				{
					clazz.CallStatic("grantPermission",
						AndroidUtils.GetCurrentActivity(), permission);
				}
				float timeElapsed = 0;
				while (isPermissionRequesting)
				{
					if ((PermissionTimeoutSecs > 0) && (timeElapsed > PermissionTimeoutSecs))
					{
						isPermissionRequesting = false;
						yield break;
					}
					timeElapsed += Time.deltaTime;
						yield return null;
				}
				callback(permission, grantResult);
			}
			else
			{
				callback(permission, PermissionGrantResult.PERMISSION_GRANT);
			}
	
			yield break;
		}

		/**
		 * 请求相机权限
		 * @param callback
		 */
		public static IEnumerator GrantCameraPermission(OnPermission callback)
		{
#if (!NDEBUG && DEBUG && ENABLE_LOG)
			Console.WriteLine($"{TAG}GrantCameraPermission:");
#endif
			if (CheckAndroidVersion(23))
			{
				// 在Android9以后，UVC设备访问也需要CAMERA权限
				yield return GrantPermission(PERMISSION_CAMERA, callback);
			}
			else
			{
				// 低于Android6不需要权限请求处理
				callback(PERMISSION_CAMERA, PermissionGrantResult.PERMISSION_GRANT);
			}

			yield break;
		}


		//================================================================================

		/**
		 * UnityPlayerActivity获得
		 */
		public static AndroidJavaObject GetCurrentActivity()
		{
			using (AndroidJavaClass playerClass = new AndroidJavaClass(FQCN_UNITY_PLAYER))
			{
				return playerClass.GetStatic<AndroidJavaObject>("currentActivity");
			}
		}

		/**
		 * 确定是否晚于指定版本
		 * @param apiLevel
		 * @return true: 在指定版本之后运行的假：在比指定版本旧的终端上运行
		 */
		public static bool CheckAndroidVersion(int apiLevel)
		{
			using (var VERSION = new AndroidJavaClass("android.os.Build$VERSION"))
			{
				return VERSION.GetStatic<int>("SDK_INT") >= apiLevel;
			}
		}

	} // class AndroidUtils

} // namespace Serenegiant

#endif // #if UNITY_ANDROID