using System;
using UnityEngine;

namespace XGame.Framework.Quality
{
    public class QualityModule : IQualityModule, IDisposable
    {
        private XQualityLevel _recommendQuality;
        public XQualityLevel RecommendQuality { get { return _recommendQuality; } }

        private XQualityLevel _curQuality;
        public XQualityLevel CurQuality { get { return _curQuality; } set { if (value != _curQuality) ChangeQualityLevel(value); } }

        public Action<XQualityLevel> OnQualityLevelChanged { get; set; }

        private Vector2Int _originalScreenSize;

        private const string SaveCurQualityKey = "CurQuality";

        //private static IQualityModule _instance;

        //public static IQualityModule Instance
        //{
        //    get
        //    {
        //        if (_instance == null) _instance = new QualityModule();
        //        return _instance;
        //    }
        //}

        public QualityModule()
        {
            _originalScreenSize = new Vector2Int(Screen.width, Screen.height);
            _curQuality = (XQualityLevel)PlayerPrefs.GetInt(SaveCurQualityKey, (int)XQualityLevel.UnKnow);
            CalcRecommendQuality();

            InnerReset();

            if (MacroDefine.IsEditor) Application.targetFrameRate = 60;
            else
            {
                Application.targetFrameRate = _curQuality == XQualityLevel.UltraHD ? 60 : 30;
            }

            Log.Info($"设备推荐的游戏品质:{_recommendQuality}，用户设置的游戏品质:{_curQuality}");
        }
        float IQualityModule.GetScreenScale()
        {
            return Screen.width * 1f / _originalScreenSize.x;
        }
        private float RecommendScreenScale(XQualityLevel level)
        {
            var scale = 1f;
            if (MacroDefine.IsAndroid)
            {
                switch (level)
                {
                    case XQualityLevel.High:
                        scale = 0.8f;
                        break;
                    case XQualityLevel.Medium:
                        scale = 0.7f;
                        break;
                    case XQualityLevel.Low:
                        scale = 0.7f;
                        break;
                }
            }
            else if (MacroDefine.IsiOS)
            {
                switch (level)
                {
                    case XQualityLevel.High:
                    case XQualityLevel.Medium:
                        scale = 0.8f;
                        break;
                    case XQualityLevel.Low:
                        scale = 0.7f;
                        break;
                }
            }
            return scale;
        }

        /// <summary>
        /// 判断是否模拟器函数
        /// 通常Android才有模拟器
        /// 模拟器可以模拟很多传感器信息
        /// 此处选用光传感器判断
        /// 实测雷电模拟器，夜神模拟器，网易mumu，腾讯手游助手都成功判断为模拟器
        /// </summary>
        /// <returns>是否模拟器</returns>
        private static bool IsSimulator()
        {
#if UNITY_ANDROID
            try
            {
                AndroidJavaClass unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
                AndroidJavaObject currentActivity = unityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity");
                AndroidJavaObject sensorManager = currentActivity.Call<AndroidJavaObject>("getSystemService", "sensor");
                AndroidJavaObject sensor = sensorManager.Call<AndroidJavaObject>("getDefaultSensor", 5); //光传感器
                return sensor == null;
            }
            catch (Exception e)
            {
                return false;
            }
#endif
            return false;
        }

        private void CalcRecommendQuality()
        {
            //显存
            int graphicsMemorySize = SystemInfo.graphicsMemorySize;
            //内存
            int systemMemorySize = SystemInfo.systemMemorySize;
            //cpu核心数
            int cpuCount = SystemInfo.processorCount;
            //cpu频率
            int cpuFrequency = SystemInfo.processorFrequency;
            
            if (MacroDefine.IsEditor)
            {
                _recommendQuality = XQualityLevel.UltraHD;
            }
            else if (MacroDefine.IsAndroid)
            {
                //模拟器
                if (IsSimulator())
                {
                    _recommendQuality = XQualityLevel.High;
                }
                //分辨率低于1344，4核心以下，主频低于1.5GHz，内存低于2GB，一律视为低端机
                else if (Math.Max(_originalScreenSize.x, _originalScreenSize.y) < 1344 || cpuCount < 4 || cpuFrequency < 1500 || systemMemorySize <= 2048)
                {
                    _recommendQuality = XQualityLevel.Low;
                }
                // 6核，内存4G，显存达到2G 高配
                else if (cpuCount >= 6 && systemMemorySize > 3072 && graphicsMemorySize >= 2048)
                {
                    _recommendQuality = XQualityLevel.High;
                }
                else
                {
                    _recommendQuality = XQualityLevel.Medium;
                }
            }
            else if (MacroDefine.IsiOS)
            {
                //iphone 8s以上
                if (SystemInfo.systemMemorySize > 2048)
                {
                    _recommendQuality = XQualityLevel.High;
                }
                else
                {
                    _recommendQuality = XQualityLevel.Medium;
                }
            }
            else
            {
                _recommendQuality = XQualityLevel.High;
            }

            if (_curQuality == XQualityLevel.UnKnow)
                ChangeQualityLevel(_recommendQuality);
        }

        private void ChangeQualityLevel(XQualityLevel ql)
        {
            // 保存
            _curQuality = ql;
            PlayerPrefs.SetInt(SaveCurQualityKey, (int)_curQuality);
            // 内部逻辑设置
            InnerReset();
            // 外部逻辑设置
            OnQualityLevelChanged?.Invoke(ql);
            Log.Info($"游戏品质等级切换到:{_curQuality}");
        }

        private void InnerReset()
        {
            // 引擎设置
            QualitySettings.SetQualityLevel((int)_curQuality);

            // 分辨率设置
            ResetResolution();

            // ShaderLod设置
            Shader.globalMaximumLOD = _curQuality.ShaderLodLevel();
        }

        // 分辨率设置
        private void ResetResolution()
        {
            if (MacroDefine.IsEditor)
                return;
            if (MacroDefine.IsAndroid || MacroDefine.IsiOS)
            {
                //var refSize = new Vector2Int(1920, 1080);
                var refLength = 1080;
                var scale = RecommendScreenScale(_curQuality);
                if (Screen.orientation == ScreenOrientation.Portrait || Screen.orientation == ScreenOrientation.PortraitUpsideDown)
                {
                    //竖屏
                    var width = (int)(refLength * scale);
                    if (width >= _originalScreenSize.x)
                    {
                        width = _originalScreenSize.x;
                    }
                    if (width != Screen.width)
                    {
                        var height = (int)(width * _originalScreenSize.y * 1f / _originalScreenSize.x);
                        Screen.SetResolution(width, height, Screen.fullScreen);
                    } 
                }
                else
                {
                    //横屏
                    var height = (int)(refLength * scale);
                    if (height >= _originalScreenSize.y)
                    {
                        height = _originalScreenSize.y;
                    }
                    if (height != Screen.height)
                    {
                        var width = (int)(height * _originalScreenSize.x * 1f / _originalScreenSize.y);
                        Screen.SetResolution(width, height, Screen.fullScreen);
                    }
                }
                
            }
        }

        void IDisposable.Dispose()
        {
            if (OnQualityLevelChanged != null)
            {
                OnQualityLevelChanged = null;
            }
        }
    }
}