//#define TEMPLY_COMMENT
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

#if  TEMPLY_COMMENT
using X2Engine.TriggerZoneManagement;
#endif

namespace X2Engine
{
    public enum EnvironmentEvent
    {
        EnvLightDirDirty
    }

    public abstract class EnvironmentComponent
    {
        private EnvironmentSystem m_parent;
        public EnvironmentSystem Parent { get { return m_parent; } set { m_parent = value; } }
        public virtual void UpdateData() { }
        public virtual void OnInit() { }
        public virtual void OnDestory() { }

        public void Broadcast(EnvironmentEvent _event)
        {
            if (m_parent)
                m_parent.SendEvent(_event);
        }

        public virtual void OnEvent(EnvironmentEvent _event) { }
    }

    [ExecuteInEditMode]
    //[RequireComponent(typeof(AtomsphereImage))]
    public class EnvironmentSystem : MonoBehaviour
    {
        public static EnvironmentSystem instance { get; private set; }
        //public EnvironmentProfile m_defaultProfile;
        public EnvironmentProfile m_profile;
        private EnvironmentProfile m_internalProfile;


        public DefaultFogConfig m_defaultFogConfig;

#if UNITY_EDITOR
        [System.NonSerialized]
        public bool m_testDefaultFog = false;
#endif

        public bool editorMode = false;

        //debug SH view
#if UNITY_EDITOR
        public Color debugEnvSkyColor;
        public Color debugEnvFrontColor;
#endif

        private bool m_bEnabledProFlare = true;

        public bool EnabledProFlare
        {
            set { m_bEnabledProFlare = value; }
            get { return m_bEnabledProFlare; }
        }

        public void LoadProfile(EnvironmentProfile profile)
        {
            if (!profile)
                return;
            m_profile = profile;
            m_internalProfile = null;

            //for (int i = 0; i < m_components.Count; ++i)
            //{
            //    m_components[i].OnInit();
            //}
        }

        public EnvironmentProfile sharedProfile
        {
            get
            {
                return m_profile;
            }
            set
            {
                //m_profile?.CopyFrom(value);

                m_profile = value;
                m_internalProfile?.CopyFrom(value);
            }
        }

        public EnvironmentProfile profile
        {
            get
            {
                //#if SCENE_EDITOR
                return m_profile;
                //#else
                //                if (m_internalProfile == null)
                //                {
                //                    m_internalProfile = ScriptableObject.CreateInstance<EnvironmentProfile>();
                //                    m_internalProfile.name = "Internal_Profile";
                //                    if (m_profile != null)
                //                    {
                //                        m_internalProfile.CopyFrom(m_profile);
                //                    }
                //                }

                //                return m_internalProfile;
                //#endif
            }
            set
            {
                m_internalProfile = value;
            }
        }

        public void ResetInternalProfile()
        {
            if (m_internalProfile == null)
            {
                m_internalProfile = ScriptableObject.CreateInstance<EnvironmentProfile>();
                m_internalProfile.name = "Internal_Profile";
            }
            if (m_profile != null)
            {
                m_internalProfile.CopyFrom(m_profile);
            }
        }


        public Light m_sun;
        public bool m_customLightDir = false;
        // public LensFlare m_lensFlare;

        public Material m_skyMaterial;
        public Material m_atomsphericScatteringMaterail;
        public Material m_precomuteMaterial;
        public Shader m_precomuteShader;
        public WeatherResources m_weatherRes;
        public GameObject m_rain;
        public GameObject m_rainFar;
        public GameObject m_snow;
        public GameObject[] m_lightingEffects;
        private GameObject m_cloud2D;
        private MeshFilter m_cloud2DMeshFilter;
        private Renderer m_cloud2DRenderer;

        private List<EnvironmentComponent> m_components = new List<EnvironmentComponent>(4);

        //private EnvironmentProfile m_lastProfile = null;
        private bool m_isRaining = false;
        public bool IsRaining
        {
            set { m_isRaining = value; }
            get { return m_isRaining; }
        }


        private Vector3 m_sunDir;
        public Vector3 SunDirection
        {
            get { return m_sunDir; }
            set { m_sunDir = value; }
        }

        private Vector3 m_moonDir;
        public Vector3 MoonDirection
        {
            get { return m_moonDir; }
            set { m_moonDir = value; }
        }


        void OnEnable()
        {
            instance = this;
            if (null == m_sun)
                m_sun = GetComponentInChildren<Light>();
            //if (null == m_lensFlare)
            //    m_lensFlare = GetComponentInChildren<LensFlare>();
            //if (null == m_lensFlare && m_sun)
            //    m_lensFlare = m_sun.gameObject.AddComponent<LensFlare>();

            if (m_sun)
            {
                m_sun.renderMode = LightRenderMode.ForcePixel;
                UnityEngine.RenderSettings.sun = m_sun;

            }

            if (m_cloud2D)
            {
                m_cloud2DMeshFilter = m_cloud2D.GetComponent<MeshFilter>();
                m_cloud2DRenderer = m_cloud2D.GetComponent<Renderer>();
            }
            else
            {
                AddCloud2DGameObject();
            }


            AddEnvComponent(new SkyEnvComponent());
            AddEnvComponent(new SkyboxComponent());
            if (AtmosphereEnvComponent.isEnableAtmosphericScattering)
            {
                AddEnvComponent(new AtmosphereEnvComponent());
            }
            AddEnvComponent(new Cloud2dEnvComponent());
            AddEnvComponent(new WeatherEnvComponent());
            AddEnvComponent(new FlashlightingComponent());
            AddEnvComponent(new BlackHoleEnvComponent());
            AddEnvComponent(new VolumetricFogEnvComponent());

            SetupComponents();

            m_bFlashLighting = false;
        }

        void OnDisable()
        {
            for (int i = 0; i < m_components.Count; ++i)
            {
                m_components[i].OnDestory();
            }
            instance = null;
            m_components.Clear();

        }

        void AddEnvComponent(EnvironmentComponent comp)
        {
            comp.Parent = this;
            m_components.Add(comp);
        }

        public EnvironmentComponent GetEvnComponent(System.Type t)
        {
            for (int i = 0; i < m_components.Count; i++)
            {
                if (m_components[i].GetType() == t)
                    return m_components[i];
            }
            return null;
        }

        private void Start()
        {
            if (PlayerPrefs.HasKey("GrassLod"))
            {
                int index = PlayerPrefs.GetInt("GrassLod");
                SetEnvironmentSystem(index == 1);
            }
        }

        public void SetEnvironmentSystem(bool active)
        {
            //var env_Environment = GameObject.Find("env_Environment");
            //if (env_Environment != null)
            //{
            //    env_Environment.GetComponent<EnvironmentSystem>().enabled = active;
            //    env_Environment.GetComponent<DayOfTime>().enabled = active;
            //}
            this.enabled = active;
            gameObject.GetComponent<DayOfTime>().enabled = active;
        }

        public void SetEnvironmentToNoon(bool active)
        {
            //var env_Environment = GameObject.Find("env_Environment");
            //if (env_Environment != null)
            //{
            //    if (active)
            //        env_Environment.GetComponent<DayOfTime>().ChangeToNoon();
            //    else
            //        env_Environment.GetComponent<DayOfTime>().BackToCurrent();


                //var environmentSystem = env_Environment.GetComponent<EnvironmentSystem>();
                //environmentSystem.pause = active;
                //if(active)
                //    environmentSystem.DoUpdate();
            //}
                // if (active)
                //     gameObject.GetComponent<DayOfTime>().ChangeToNoon();
                // else
                //     gameObject.GetComponent<DayOfTime>().BackToCurrent();

            SetEnvironmentToNoon( active, 0);
        }

        public void SetEnvironmentToNoon(bool active, int time)
        {
            SetEnvironmentToTime( active, time);
        }

        public void SetEnvironmentToTime(bool active,float time)
        {
           DayOfTime dayOfTime=  gameObject.GetComponent<DayOfTime>();
            if (active)
               dayOfTime.ChangeToTime(time);
            else
                dayOfTime.BackToCurrent();

            if(active)
            {
                dayOfTime.DoUpdate();
                DoUpdate();
              
            }
            pause = active;    
        }
        private bool rainisactive = false;
        private bool snowisactive = false;
        bool rainFarisactive = false;
        public void SetWeatherSystem(bool active)
        {
            if(active==false)
            {
                rainisactive = m_rain.activeInHierarchy;
                snowisactive = m_snow.activeInHierarchy;
                rainFarisactive = m_rainFar.activeInHierarchy;
                m_rain.SetActive(active);
                m_snow.SetActive(active);
                m_rainFar.SetActive(active);
            }
            else
            {
                m_rain.SetActive(rainisactive);
                m_snow.SetActive(snowisactive);
                m_rainFar.SetActive(rainFarisactive);
            }
           
        }
        
        public bool SetFogEnable(bool enable)
        {
            if(pause==true)
            {
                if (profile != null)
                {
                    //AB对话 临时关闭 fog  结束对话后  开始更新 会自动更加设置打开或者不打开
                    profile.atmosphericScattering.enable = enable;
                    return true;
                }
                return false;
            }
            return false;
        } 
           

        public bool pause =false;
        //#if UNITY_EDITOR && SCENE_EDITOR
        private void Update()
        {
            if(pause ==false)
                DoUpdate();
          
        }
        //#endif

        public void DoUpdate()
        {
            //if (!sharedProfile)
            //    return;

            //if (m_lastProfile != sharedProfile)
            //{
            //    m_lastProfile = sharedProfile;
            //    IEventDispatchManager.Instance.Invoke(GlobalEventID.ENVIRONMENT_PROFILE_CHANGED, 0);
            //}

            for (int i = 0; i < m_components.Count; ++i)
            {
#if UNITY_EDITOR
                UnityEngine.Profiling.Profiler.BeginSample(m_components[i].GetType().Name);
#endif
                m_components[i].UpdateData();
#if UNITY_EDITOR
                UnityEngine.Profiling.Profiler.EndSample();
#endif
            }

            if (m_bFlashLighting)
            {
                if (Time.time > m_flashLightingEndTime)
                {
                    m_bFlashLighting = false;
                    m_flashLightingIntensity = 0;
                }
            }
        }

        void SetupComponents()
        {
            if (!profile)
                return;
            for (int i = 0; i < m_components.Count; ++i)
            {
                m_components[i].OnInit();
            }
        }

        private bool m_bFlashLighting = false;
        private float m_flashLightingIntensity = 0;
        private float m_flashLightingEndTime;
        public void TiggerFlashLighting(float sec, float intensity)
        {
            m_flashLightingEndTime = Time.time + sec;
            m_flashLightingIntensity = intensity;
            m_bFlashLighting = true;
        }

        public float GetFlashLightIntensity()
        {
            if (m_bFlashLighting)
            {
                return m_flashLightingIntensity;
            }

            return 0;
        }


        //#if  TEMPLY_COMMENT
        public void TiggerLightingEffects(int groupID, float dir)
        {
            if (m_lightingEffects.Length == 0)
                return;
            if (groupID >= m_lightingEffects.Length)
                groupID = 0;

            var lightingGo = m_lightingEffects[groupID];
            if (null == lightingGo) return;

            var cam = CameraCache.main;
            if (null == cam) return;

            lightingGo.transform.parent.SetPositionAndRotation(cam.transform.position, Quaternion.Euler(0f, dir, 0));
            var animation = lightingGo.GetComponent<Animation>();
            animation?.Play();
        }
        //#endif


        public void SendEvent(EnvironmentEvent _event)
        {
            if (!profile)
                return;

            for (int i = 0; i < m_components.Count; ++i)
            {
                m_components[i].OnEvent(_event);
            }
        }


        void AddCloud2DGameObject()
        {
            GameObject cloudGo = new GameObject();
            cloudGo.name = "Cloud2D";
            cloudGo.layer = 0;
            cloudGo.hideFlags = HideFlags.HideAndDontSave;
            var mf = cloudGo.AddComponent<MeshFilter>();
            var mr = cloudGo.AddComponent<MeshRenderer>();
            //mf.mesh = mesh;
            //mr.material = matCloud;
            cloudGo.transform.SetParent(transform);

            m_cloud2D = cloudGo;
            m_cloud2DMeshFilter = mf;
            m_cloud2DRenderer = mr;
        }

        public void SetCloud2DMeshAndMaterial(Mesh mesh, Material mat)
        {
            if (mat != null)
            {
                if (m_cloud2DMeshFilter.gameObject.activeSelf == false)
                    m_cloud2DMeshFilter.gameObject.SetActive(true);
                if (m_cloud2DMeshFilter)
                    m_cloud2DMeshFilter.sharedMesh = mesh;

                if (m_cloud2DRenderer)
                    m_cloud2DRenderer.sharedMaterial = mat;
            }
            else
            {
                if (m_cloud2DMeshFilter.gameObject.activeSelf == true)
                    m_cloud2DMeshFilter.gameObject.SetActive(false);
            }

        }


        public bool GetDefaultFogSetting(ref DefaultFogSettings setting)
        {
            int weather = 0;
            if (m_defaultFogConfig != null && m_defaultFogConfig.settings.Length > 0)
            {
                //if (TriggerZoneManager.singleton != null)
                //    weather = TriggerZoneManager.singleton.Weather;
                weather = System.Math.Min(weather, m_defaultFogConfig.settings.Length);
                setting = m_defaultFogConfig.settings[weather];
                return true;
            }
            return false;
        }
    }
}
