using UnityEngine;
using System;
using System.Collections;
using System.Runtime.InteropServices;


public enum VibrationType {
    None,
    Once,
    OnceStrong,
    OnceWeak,
    DoubleStrong,
    DoubleWeak,
    Triple,
}

public static class NativeUtils { 

    // Vibration Effect Type 
    public static readonly string vEffectOneShot = "EFFECT_DEFAULT_AMPLITUDE";
    public static readonly string vEffectClick = "EFFECT_CLICK";
    public static readonly string vEffectDClick = "EFFECT_DOUBLE_CLICK";
    public static readonly string vEffectHClick = "EFFECT_HEAVY_CLICK";
    public static readonly string vEffectTick = "EFFECT_TICK";

#if UNITY_EDITOR
#elif UNITY_IOS
	[DllImport("__Internal")]
    private static extern int _getHeight();
    [DllImport("__Internal")]
    private static extern int _getWidth();
	[DllImport("__Internal")]
    private static extern int _getPointHeight();
    [DllImport("__Internal")]
    private static extern int _getPointWidth();
    [DllImport("__Internal")]
    private static extern bool _enableReviewWindow();    
    [DllImport("__Internal")]
    private static extern int _reviewWindow(string appid);
    [DllImport("__Internal")]
    private static extern long _systemClockTime();

    [DllImport("__Internal")]
    private static extern bool _canOpenTwitter();
    [DllImport("__Internal")]
    private static extern bool _canOpenFacebook();

    [DllImport("__Internal")]
    private static extern void _registerNotification();
    [DllImport("__Internal")]
    private static extern void _scheduleNotification(int triggerInSeconds, string message, string alarmId);
    [DllImport("__Internal")]
    private static extern void _cancelAllNotifications();
    [DllImport("__Internal")]
    private static extern void _PlayVibration(int id);
    [DllImport("__Internal")]
    private static extern void _PlayVibrationOnce();
    [DllImport("__Internal")]
    private static extern void _PlayVibrationOnceStrong();
    [DllImport("__Internal")]
    private static extern void _PlayVibrationOnceWeak();
    [DllImport("__Internal")]
    private static extern void _PlayVibrationDoubleStrong();
    [DllImport("__Internal")]
    private static extern void _PlayVibrationDoubleWeak();
    [DllImport("__Internal")]
    private static extern void _PlayVibrationTriple();

    [DllImport("__Internal")]
    private static extern void _showAlert(string title, string message);

#elif UNITY_ANDROID

    private static void _Vibration(){
        Handheld.Vibrate();
    }
    private static void _VibrationAndroid(string effectType, long msec = 100){
        using (AndroidJavaClass cls = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        using (AndroidJavaObject jo = cls.GetStatic<AndroidJavaObject>("currentActivity"))
        using (AndroidJavaObject vibrator = jo.Call<AndroidJavaObject>("getSystemService", "vibrator"))
        {
            if(androidOSVersion() >= 26 )
            {
                using (AndroidJavaClass vCls = new AndroidJavaClass("android.os.VibrationEffect"))
                {
                    AndroidJavaObject vEffect = default;
                    if( effectType != NativeUtils.vEffectOneShot && androidOSVersion() >= 29)
                    {
                        vEffect = vCls.CallStatic<AndroidJavaObject>("createPredefined", vCls.GetStatic<int>(effectType));
                    }
                    else
                    {
                        vEffect = vCls.CallStatic<AndroidJavaObject>("createOneShot", new object[] { msec, vCls.GetStatic<int>("DEFAULT_AMPLITUDE") });
                    }
                    vibrator.Call("vibrate", vEffect);
                }
            }
            else
            {
                vibrator.Call("vibrate", msec);
            }
        }
    }

    private static int androidOSVersion() {
#if !UNITY_EDITOR
        using (var version = new AndroidJavaClass("android.os.Build$VERSION"))
        {
            return version.GetStatic<int>("SDK_INT");
        }
#else
        return -1;
#endif        
    }

#endif

    public static int getHeight(){
        int height = 0;
#if UNITY_EDITOR
        height = Screen.height;
#elif UNITY_IOS
        height = _getHeight();
#elif UNITY_ANDROID
        using (AndroidJavaClass cls = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        using (AndroidJavaObject jo = cls.GetStatic<AndroidJavaObject>("currentActivity"))
        {
            height = (int)jo.Call<float>("getHeightPixels");
        }
#endif
        return height;
    }
    public static int getWidth(){
        int width = 0;
#if UNITY_EDITOR
        width = Screen.width;
#elif UNITY_IOS
        width = _getWidth();
#elif UNITY_ANDROID
        using (AndroidJavaClass cls = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        using (AndroidJavaObject jo = cls.GetStatic<AndroidJavaObject>("currentActivity"))
        {
            width = (int)jo.Call<float>("getWidthPixels");
        }
#endif
        return width;
    }

    public static int getPointHeight(){
        int height = 0;
        #if UNITY_EDITOR
            height = Screen.height;
		#elif UNITY_IOS
		if (Application.platform != RuntimePlatform.OSXEditor) {
            height = _getPointHeight();
		}
		#elif UNITY_ANDROID
        using (AndroidJavaClass cls = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        using (AndroidJavaObject jo = cls.GetStatic<AndroidJavaObject>("currentActivity"))
        {
            height = (int)jo.Call<float>("getPointHeight");
        }
		#endif



        return height;
	}
    public static int getPointWidth(){
        int width = 0;
        #if UNITY_EDITOR
            width = Screen.width;
		#elif UNITY_IOS && !UNITY_EDITOR
		if (Application.platform != RuntimePlatform.OSXEditor) {
            width = _getPointWidth();
		}
		#elif UNITY_ANDROID && !UNITY_EDITOR
        using (AndroidJavaClass cls = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        using (AndroidJavaObject jo = cls.GetStatic<AndroidJavaObject>("currentActivity"))
        {
            width = (int)jo.Call<float>("getPointWidth");
        }
		#endif

        return width;
	}

    public static void forceOrientationLandscape(){
#if UNITY_EDITOR
#elif UNITY_IOS
#elif UNITY_ANDROID
        using (AndroidJavaClass cls = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        using (AndroidJavaObject jo = cls.GetStatic<AndroidJavaObject>("currentActivity"))
        {
            jo.Call("forceOrientationLandscape");
        }
#endif
    }
    public static void forceOrientationPortrait(){
#if UNITY_EDITOR
#elif UNITY_IOS
#elif UNITY_ANDROID
        using (AndroidJavaClass cls = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        using (AndroidJavaObject jo = cls.GetStatic<AndroidJavaObject>("currentActivity"))
        {
            jo.Call("forceOrientationPortrait");
        }
#endif
    }    

    public static bool enableReviewWindow(){
        bool res = false;
#if UNITY_IOS && !UNITY_EDITOR
    if (Application.platform != RuntimePlatform.OSXEditor) {
        res = _enableReviewWindow();
    }
#endif
        return res;
    }

    public static void reviewWindow( string appid){
        #if UNITY_IOS && !UNITY_EDITOR
        if (Application.platform != RuntimePlatform.OSXEditor) {
            _reviewWindow(appid);
        }
        #endif
    }

    /// <summary>
    /// 端末起動からの経過時間（s）
    /// </summary>
    public static long systemClockTime(){

        long res = 0;
        #if UNITY_EDITOR
            var start = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            res =　(long)(DateTime.Now.ToUniversalTime() - start).TotalSeconds;      
		#elif UNITY_IOS && !UNITY_EDITOR
		if (Application.platform != RuntimePlatform.OSXEditor) {
            res = _systemClockTime();
		}
		#elif UNITY_ANDROID && !UNITY_EDITOR
        using (AndroidJavaClass cls = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        using (AndroidJavaObject jo = cls.GetStatic<AndroidJavaObject>("currentActivity"))
        {
            res = (long)(jo.Call<long>("elapsedRealtime") / 1000);
        }
		#endif

        return res;
    }

#if UNITY_ANDROID
    public static int getAndroidApiLevel(){
        var cls = new AndroidJavaClass("android.os.Build$VERSION");
        var apiLevel = cls.GetStatic<int>("SDK_INT");
        Debug.Log(apiLevel);
        return apiLevel;
    }
#elif UNITY_EDITOR
#elif UNITY_IOS
    public static bool canOpenTwitter(){
        return _canOpenTwitter();
    }
    public static bool canOpenFacebook(){
        return _canOpenFacebook();
    }

    public static int GetiOSMajorVersion(){
        string version = SystemInfo.operatingSystem;
        version = version.Split('.')[0];
        string[] stringSplits = version.Split(' ');
        version = stringSplits[stringSplits.Length -1];
        return int.Parse(version);
    }
#endif
    public static void InitNotification()
    {
#if UNITY_EDITOR
#elif UNITY_IOS
#elif UNITY_ANDROID
       // UniLocalNotification.Initialize();
#endif
    }

    public static void RegisterNotification()
    {
#if UNITY_EDITOR
#elif UNITY_IOS
        _registerNotification();
#elif UNITY_ANDROID
#endif
    }
    public static void ScheduleNotification(int triggerInSeconds, string title, string message, int id)
    {
#if UNITY_EDITOR
#elif UNITY_IOS
        _scheduleNotification(triggerInSeconds, message, id.ToString());
#elif UNITY_ANDROID
       // UniLocalNotification.Register(triggerInSeconds, message, title);
#endif
    }
    public static void CancelAllNotifications(){
#if UNITY_EDITOR
#elif UNITY_IOS
        _cancelAllNotifications();
#elif UNITY_ANDROID
        // UniLocalNotification.CancelAll();
#endif
    }

    public static void PlayVibration(VibrationType vibrationType){
        switch(vibrationType){
        case VibrationType.Once:
            PlayVibrationOnce();
            break;
        case VibrationType.OnceStrong:
            PlayVibrationOnceStrong();
            break;
        case VibrationType.OnceWeak:
            PlayVibrationOnceWeak();
            break;
        case VibrationType.DoubleStrong:
            PlayVibrationDoubleStrong();
            break;
        case VibrationType.DoubleWeak:
            PlayVibrationDoubleWeak();
            break;
        case VibrationType.Triple:
            PlayVibrationTriple();
            break;
        }
    }

    public static void PlayVibrationOnce(){
#if UNITY_EDITOR
#elif UNITY_IOS
        _PlayVibrationOnce();
#elif UNITY_ANDROID
        _VibrationAndroid(NativeUtils.vEffectClick, 20);
#endif
    }
    public static void PlayVibrationOnceStrong(){
#if UNITY_EDITOR
#elif UNITY_IOS
        _PlayVibrationOnceStrong();
#elif UNITY_ANDROID
        _VibrationAndroid(NativeUtils.vEffectHClick, 50);
#endif
    }
    public static void PlayVibrationOnceWeak(){
#if UNITY_EDITOR
#elif UNITY_IOS
        _PlayVibrationOnceWeak();
#elif UNITY_ANDROID
        _VibrationAndroid(NativeUtils.vEffectTick, 10);
#endif
    }
    public static void PlayVibrationDoubleStrong(){
#if UNITY_EDITOR
#elif UNITY_IOS
        _PlayVibrationDoubleStrong();
#elif UNITY_ANDROID
        _VibrationAndroid(NativeUtils.vEffectDClick, 80);
#endif
    }
    public static void PlayVibrationDoubleWeak(){
#if UNITY_EDITOR
#elif UNITY_IOS
        _PlayVibrationDoubleWeak();
#elif UNITY_ANDROID
        _VibrationAndroid(NativeUtils.vEffectOneShot, 100); // TODO:最適化
#endif
    }
    public static void PlayVibrationTriple(){
#if UNITY_EDITOR
#elif UNITY_IOS
        _PlayVibrationTriple();
#elif UNITY_ANDROID
        _VibrationAndroid(NativeUtils.vEffectOneShot, 200); // TODO:最適化
#endif
    }

    public static void ShowAlert(string title, string message){
#if UNITY_EDITOR
#elif UNITY_IOS
        _showAlert(title, message);
#elif UNITY_ANDROID
// TODO:
#endif
    }
}


