using System.Collections;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;

namespace X2Engine
{
    public class WeatherEnvComponent : EnvironmentComponent
    {
        static readonly int m_sp_rainParams0 = Shader.PropertyToID("rainParams0");
        static readonly int m_sp_rainParams1 = Shader.PropertyToID("rainParams1");
        static readonly int m_sp_rainRippleTex = Shader.PropertyToID("rainRipplesTex");
        static readonly int m_sp_FarRainIntensity = Shader.PropertyToID("_FarRainIntensity");
        static readonly int m_sp_NearRainIntensity = Shader.PropertyToID("_NearRainIntensity");
  
        private int m_rainRippleTexIndex = 0;

        private Camera m_cam = null;
        public WeatherEnvComponent()
        {
        }

        public override void OnInit()
        {
            m_rainRippleTexIndex = 0;
            var profile = Parent.profile.weatherSystem;
            SetWeatherSystemShaderUniform(profile);
        }

        public override void OnDestory()
        {
            
        }

        void UpdateRippleTexIndex(int texSize)
        {
            float elapsedTime = Time.time;
            float AnimTexFlipTime = 0.05f;
            m_rainRippleTexIndex = (int)(elapsedTime / AnimTexFlipTime) % texSize;
        }

        void SetWeatherSystemShaderUniform(WeatherSystemSettings profile)
        {
            Shader.SetGlobalVector(
                m_sp_rainParams0,
                new Vector4(profile.isRaining ? profile.rainningAmount : 0, profile.rainningAmount * profile.puddleAmount,
                    profile.puddleRipplesScale, 0)
                //new Vector4(profile.rainningAmount, profile.rainningAmount * profile.puddleAmount,
                //    profile.puddleRipplesScale, 0)
                );
            Shader.SetGlobalVector(
                m_sp_rainParams1, 
                new Vector4(0, 0, profile.puddleRipplesAmount, profile.diffuseDarkening)
                );
            Shader.SetGlobalFloat(
                m_sp_FarRainIntensity,
                profile.farRainDropIntensity * profile.rainningAmount
                );
            Shader.SetGlobalFloat(
                m_sp_NearRainIntensity,
                profile.nearRainDropIntensity * profile.rainningAmount
                );

            var rippleTex = Parent.m_weatherRes ? Parent.m_weatherRes.ripples : null;
            if (rippleTex!= null && rippleTex.Length > 0)
            {
                UpdateRippleTexIndex(rippleTex.Length);
                Shader.SetGlobalTexture(m_sp_rainRippleTex, rippleTex[m_rainRippleTexIndex]);
            }
            //if(LSS.ReflectionMgr.Instance != null)
            //{
            //    LSS.ReflectionMgr.Instance.RpOutdoorStrength = profile.rpOutDoorStrength;
            //}
      
        }

        public override void UpdateData()
        {
            if(Parent.profile)
            {
                var profile = Parent.profile.weatherSystem;
                m_cam = CameraCache.main;
                SetWeatherSystemShaderUniform(profile);
                UpdateRain(profile);
                UpdateSnow(profile);
            }
            
        }

        private void UpdateRain(WeatherSystemSettings profile)
        {
            bool isRainning = profile.isRaining && profile.rainningAmount > 0.001f;
            //bool isRainning = profile.rainningAmount > 0.001f;
            Parent.IsRaining = isRainning;
            if (isRainning && m_cam)
            {
                if (Parent.m_rain)
                {
                    Parent.m_rain.SetActive(true);
                    Parent.m_rain.transform.position = m_cam.transform.position + m_cam.transform.forward * 5.0f/*profile.nearRainDropDistance*/;
                }
                if (Parent.m_rainFar)
                {
                    Parent.m_rainFar.SetActive(true);
                    Parent.m_rainFar.transform.position = m_cam.transform.position;
                }
            }
            else
            {
                if (Parent.m_rain)
                    Parent.m_rain.SetActive(false);
                if (Parent.m_rainFar)
                    Parent.m_rainFar.SetActive(false);
            }
        }


        private void UpdateSnow(WeatherSystemSettings profile)
        {
            if (profile.isSnowing && m_cam)
            {
                if (Parent.m_snow)
                {
                    Parent.m_snow.SetActive(true);
                    Parent.m_snow.transform.position = m_cam.transform.position;
                }
            }
            else
            {
                if (Parent.m_snow)
                    Parent.m_snow.SetActive(false);
            }
        }

    }


    public class FlashlightingComponent : EnvironmentComponent
    {
        private bool isFlashing = false;
        public const string startFilePath = "Asset/art_resource/WeatherSystem/";
        private const string flashlightingFileName = "flashlighting";

        private FlashLightingAssets.FlashLightingSingleInfo[] m_fInfos;
        private FlashLightingAssets.FlashLightingCycleSingleInfo[] m_fCycleInfos;

        private Dictionary<int, List<FlashLightingAssets.FlashLightingInfo>> m_cycleDecomposes = new Dictionary<int, List<FlashLightingAssets.FlashLightingInfo>>(5);

        private List<FlashLightingAssets.FlashLightingInfo> m_currRunList = null;
        private int m_currRunIndex = 0;
        private FlashLightingAssets.FlashLightingInfo m_currRunInfo = null;


        private bool isOpenTimer = false;
        private float m_currTime = 0;
        private string m_soundEventName = "";//闪电声音;


        class flashEffectData
        {
            public int id;
            public float currTime = 0;
        }

        private List<flashEffectData> m_flashDataList = new List<flashEffectData>(0);
        private float m_flashEffectKeepTime = 3;
        bool isActiveCheckFlashEffectData = false;


        public override void OnInit()
        {
            UnityEngine.Object o = null;// ResourceHelper.LoadResourceSync(startFilePath, flashlightingFileName, IResourceLoader.strAssetSuffix);

            string assetPath = string.Concat(startFilePath, flashlightingFileName);
            if (Application.isPlaying)
                o = ResourceManager.Instance.Load<FlashLightingAssets>(assetPath, ".asset");
#if UNITY_EDITOR
            else
            {
     
                o = UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEngine.Object>("Assets/AssetBundles/" + assetPath + ".asset");
            }
#endif

            if (o != null)
            {
                m_fInfos = (o as FlashLightingAssets).infos;
                m_fCycleInfos = (o as FlashLightingAssets).cycleInfos;
            }

            if ((m_fInfos != null) && (m_fCycleInfos != null))
            {
                decomposeCycle();
            }

            m_cycleDecomposes.TryGetValue(1, out m_currRunList);
            moveToNextFlashLightingInfo();
            StartFlashLighting();

        }


        public override void OnDestory()
        {

        }

        private void decomposeCycle()
        {
            m_cycleDecomposes.Clear();

            FlashLightingAssets.FlashLightingCycleSingleInfo temp = null;
            for (int i = 0, count = m_fCycleInfos.Length; i < count; ++i)
            {
                List<FlashLightingAssets.FlashLightingInfo> one = new List<FlashLightingAssets.FlashLightingInfo>(10);

                temp = m_fCycleInfos[i];

                FlashLightingAssets.FlashLightingCycleInfo tempInfo = null;
                for (int k = 0, len = temp.infos.Length; k < len; ++k)
                {
                    tempInfo = temp.infos[k];
                    float delay = tempInfo.delay;

                    FlashLightingAssets.FlashLightingSingleInfo fsInfo = getFlashLightingSingleInfoById(tempInfo.singleId);

                    if (fsInfo != null)
                    {
                        for (int t = 0, tCount = fsInfo.infos.Length; t < tCount; ++t)
                        {
                            FlashLightingAssets.FlashLightingInfo fi = new FlashLightingAssets.FlashLightingInfo();
                            if (t == 0)
                            {
                                fi.delay = delay + fsInfo.infos[t].delay;
                            }
                            else
                            {
                                fi.delay = fsInfo.infos[t].delay;
                            }

                            fi.length = fsInfo.infos[t].length;
                            fi.intensity = fsInfo.infos[t].intensity;

                            one.Add(fi);
                        }
                    }
                }

                m_cycleDecomposes[temp.id] = one;
            }
        }

        private FlashLightingAssets.FlashLightingSingleInfo getFlashLightingSingleInfoById(int id)
        {
            for (int i = 0, count = m_fInfos.Length; i < count; ++i)
            {
                if (m_fInfos[i].id == id)
                {
                    return m_fInfos[i];
                }
            }

            return null;
        }

        private void resetFlashEffectTime(int id)
        {
            for (int i = 0, len = m_flashDataList.Count; i < len; ++i)
            {
                if (m_flashDataList[i].id == id)
                {
                    m_flashDataList[i].currTime = m_flashEffectKeepTime;
                    isActiveCheckFlashEffectData = true;

                    return;
                }
            }

            flashEffectData fd = new flashEffectData();
            fd.id = id;
            fd.currTime = m_flashEffectKeepTime;
            m_flashDataList.Add(fd);
            isActiveCheckFlashEffectData = true;
        }

        private bool isFlashEffectActive(int id)
        {
            for (int i = 0, len = m_flashDataList.Count; i < len; ++i)
            {
                if (m_flashDataList[i].id == id)
                {
                    return (m_flashDataList[i].currTime > 0);
                }
            }

            return false;
        }

        private bool tiggerFlashLightingAndPlaySound(FlashLightingAssets.FlashLightingInfo info)
        {
            if (!EnvironmentSystem.instance) return false;

            if (info != null)
            {
                EnvironmentSystem.instance.TiggerFlashLighting(info.length, info.intensity);

                Vector3 e = CameraCache.main.transform.eulerAngles;

                //EnvironmentSystem.instance.TiggerLightingEffects(0, e.y);

                int id = UnityEngine.Random.Range(0, 3);

                if (!isFlashEffectActive(id))
                {
                    resetFlashEffectTime(id);
                    EnvironmentSystem.instance.TiggerLightingEffects(id, UnityEngine.Random.Range(e.y - 30, e.y + 30));
                }
                //AudioCtrl.PlaySound(m_soundEventName);
            }

            return true;
        }

        public void TiggerFlashLightingById(int id, string soundEventName)
        {
            if (isFlashing)
            {
                m_soundEventName = soundEventName;

                m_currRunList = null;
                m_cycleDecomposes.TryGetValue(id, out m_currRunList);

                if (m_currRunList != null)
                {
                    if (m_currRunList.Count > 0)
                    {
                        m_currRunIndex = m_currRunList.Count;

                        moveToNextFlashLightingInfo();

                        m_currTime = 0;
                        isOpenTimer = true;
                    }
                }
            }
        }

        public void StartFlashLighting()
        {
            isFlashing = true;
        }

        public void StopFlashLighting()
        {
            isFlashing = false;
        }

        public bool isCurrFlashing()
        {
            return isFlashing;
        }

        private void moveToNextFlashLightingInfo()
        {
            if (m_currRunList != null)
            {
                if ((m_currRunList.Count - 1) > m_currRunIndex)
                {
                    m_currRunIndex = m_currRunIndex + 1;
                }
                else
                {
                    m_currRunIndex = 0;
                }

                m_currRunInfo = m_currRunList[m_currRunIndex];
            }
        }

        public override void UpdateData()
        {
            if (Parent.profile)
            {
                var profile = Parent.profile.weatherSystem;
                if(profile.isFlashLighting)
                {
                    if (m_currRunInfo != null)
                    {
                        m_currTime = m_currTime + Time.deltaTime;
                        if (m_currTime >= m_currRunInfo.delay)
                        {
                            m_currTime = 0;

                            if (isFlashing)
                            {
                                tiggerFlashLightingAndPlaySound(m_currRunInfo);

                                moveToNextFlashLightingInfo();
                            }
                            else
                            {
                                isOpenTimer = false;
                            }
                        }
                    }
                }
            }

        }

    }
}

