using System;
using GraphiXNA.Cameras;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace GraphiXNA.Materials
{
    public class ParallaxOcclusionMapping : MaterialEffect
    {
        private EffectParameter parameter_g_baseTexture = null;
        private EffectParameter parameter_g_nmhTexture = null;
        private EffectParameter parameter_g_materialAmbientColor = null;
        private EffectParameter parameter_g_materialDiffuseColor = null;
        private EffectParameter parameter_g_materialSpecularColor = null;
        private EffectParameter parameter_g_fSpecularExponent = null;
        private EffectParameter parameter_g_bAddSpecular = null;
        private EffectParameter parameter_g_LightDir = null;
        private EffectParameter parameter_g_LightDiffuse = null;
        private EffectParameter parameter_g_LightAmbient = null;
        private EffectParameter parameter_g_vEye = null;
        private EffectParameter parameter_g_fBaseTextureRepeat = null;
        private EffectParameter parameter_g_fHeightMapScale = null;
        private EffectParameter parameter_g_mWorld = null;
        private EffectParameter parameter_g_mWorldViewProjection = null;
        private EffectParameter parameter_g_mView = null;
        private EffectParameter parameter_g_bVisualizeLOD = null;
        private EffectParameter parameter_g_bVisualizeMipLevel = null;
        private EffectParameter parameter_g_bDisplayShadows = null;
        private EffectParameter parameter_g_vTextureDims = null;
        private EffectParameter parameter_g_nLODThreshold = null;
        private EffectParameter parameter_g_fShadowSoftening = null;
        private EffectParameter parameter_g_nMinSamples = null;
        private EffectParameter parameter_g_nMaxSamples = null;

        public Vector4 AmbientColor;
        public Vector4 DiffuseColor;
        public Vector4 SpecularColor;
        public float SpecularExponent;
        public bool AddSpecular;
        public Vector3 LightDirection;
        public Vector4 LightDiffuse;
        public Vector4 LightAmbient;
        public float TextureRepeat;
        public float HeightMapScale;
        public bool VisualizeLOD;
        public bool VisualizeMipLevel;
        public bool DisplayShadows;
        private Vector2 TextureDimentions;
        public int LODThreshold;
        public float ShadowSoftening;
        public int MinSamples;
        public int MaxSamples;

        public Texture2D ColorTexture = null;
        public Texture2D NormalHeightTexture = null;

        public ParallaxOcclusionMapping(GraphicsDevice graphicsDevice)
            : base(graphicsDevice)
        {
            _Effect = ResourceManager.GetParallaxOcclusionMappingEffect(GraphicsDevice, false);

            parameter_g_baseTexture = _Effect.Parameters["g_baseTexture"];
            parameter_g_nmhTexture = _Effect.Parameters["g_nmhTexture"];
            parameter_g_materialAmbientColor = _Effect.Parameters["g_materialAmbientColor"];
            parameter_g_materialDiffuseColor = _Effect.Parameters["g_materialDiffuseColor"];
            parameter_g_materialSpecularColor = _Effect.Parameters["g_materialSpecularColor"];
            parameter_g_fSpecularExponent = _Effect.Parameters["g_fSpecularExponent"];
            parameter_g_bAddSpecular = _Effect.Parameters["g_bAddSpecular"];
            parameter_g_LightDir = _Effect.Parameters["g_LightDir"];
            parameter_g_LightDiffuse = _Effect.Parameters["g_LightDiffuse"];
            parameter_g_LightAmbient = _Effect.Parameters["g_LightAmbient"];
            parameter_g_vEye = _Effect.Parameters["g_vEye"];
            parameter_g_fBaseTextureRepeat = _Effect.Parameters["g_fBaseTextureRepeat"];
            parameter_g_fHeightMapScale = _Effect.Parameters["g_fHeightMapScale"];
            parameter_g_mWorld = _Effect.Parameters["g_mWorld"];
            parameter_g_mWorldViewProjection = _Effect.Parameters["g_mWorldViewProjection"];
            parameter_g_mView = _Effect.Parameters["g_mView"];
            parameter_g_bVisualizeLOD = _Effect.Parameters["g_bVisualizeLOD"];
            parameter_g_bVisualizeMipLevel = _Effect.Parameters["g_bVisualizeMipLevel"];
            parameter_g_bDisplayShadows = _Effect.Parameters["g_bDisplayShadows"];
            parameter_g_vTextureDims = _Effect.Parameters["g_vTextureDims"];
            parameter_g_nLODThreshold = _Effect.Parameters["g_nLODThreshold"];
            parameter_g_fShadowSoftening = _Effect.Parameters["g_fShadowSoftening"];
            parameter_g_nMinSamples = _Effect.Parameters["g_nMinSamples"];
            parameter_g_nMaxSamples = _Effect.Parameters["g_nMaxSamples"];

            AddSpecular = parameter_g_bAddSpecular.GetValueBoolean();
            DisplayShadows = parameter_g_bDisplayShadows.GetValueBoolean();
            VisualizeLOD = parameter_g_bVisualizeLOD.GetValueBoolean();
            VisualizeMipLevel = parameter_g_bVisualizeMipLevel.GetValueBoolean();
            TextureRepeat = parameter_g_fBaseTextureRepeat.GetValueSingle();
            HeightMapScale = parameter_g_fHeightMapScale.GetValueSingle();
            ShadowSoftening = parameter_g_fShadowSoftening.GetValueSingle();
            SpecularExponent = parameter_g_fSpecularExponent.GetValueSingle();
            LightAmbient = parameter_g_LightAmbient.GetValueVector4();
            LightDiffuse = parameter_g_LightDiffuse.GetValueVector4();
            LightDirection = parameter_g_LightDir.GetValueVector3();
            AmbientColor = parameter_g_materialAmbientColor.GetValueVector4();
            DiffuseColor = parameter_g_materialDiffuseColor.GetValueVector4();
            SpecularColor = parameter_g_materialSpecularColor.GetValueVector4();
            LODThreshold = parameter_g_nLODThreshold.GetValueInt32();
            MaxSamples = parameter_g_nMaxSamples.GetValueInt32();
            MinSamples = parameter_g_nMinSamples.GetValueInt32();
        }

        public override void SetWorld(Camera camera, ref Matrix world)
        {
            parameter_g_mView.SetValue(camera._View);
            parameter_g_mWorld.SetValue(world);
            parameter_g_mWorldViewProjection.SetValue(world * camera._ViewProjection);
            parameter_g_vEye.SetValue(camera.Position);
        }

        internal override void OnBegin()
        {
            parameter_g_baseTexture.SetValue(ColorTexture);
            parameter_g_nmhTexture.SetValue(NormalHeightTexture);

            if (ColorTexture != null)
            {
                TextureDimentions.X = ColorTexture.Width;
                TextureDimentions.Y = ColorTexture.Height;
            }
            else
            {
                TextureDimentions.X = 0;
                TextureDimentions.Y = 0;
            }

            parameter_g_vTextureDims.SetValue(TextureDimentions);

            parameter_g_bAddSpecular.SetValue(AddSpecular);
            parameter_g_bDisplayShadows.SetValue(DisplayShadows);
            parameter_g_bVisualizeLOD.SetValue(VisualizeLOD);
            parameter_g_bVisualizeMipLevel.SetValue(VisualizeMipLevel);
            parameter_g_fBaseTextureRepeat.SetValue(TextureRepeat);
            parameter_g_fHeightMapScale.SetValue(HeightMapScale);
            parameter_g_fShadowSoftening.SetValue(ShadowSoftening);
            parameter_g_fSpecularExponent.SetValue(SpecularExponent);
            parameter_g_LightAmbient.SetValue(LightAmbient);
            parameter_g_LightDiffuse.SetValue(LightDiffuse);
            parameter_g_LightDir.SetValue(LightDirection);
            parameter_g_materialAmbientColor.SetValue(AmbientColor);
            parameter_g_materialDiffuseColor.SetValue(DiffuseColor);
            parameter_g_materialSpecularColor.SetValue(SpecularColor);
            parameter_g_nLODThreshold.SetValue(LODThreshold);
            parameter_g_nMaxSamples.SetValue(MaxSamples);
            parameter_g_nMinSamples.SetValue(MinSamples);
            
        }
    }
}
