using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.Generic;

namespace GraphiXNA.ParticleSystems
{
    /// <summary>
    /// The main component in charge of displaying particles.
    /// </summary>
    public abstract class ParticleSystem
    {
        List<ParticleEmitter> emitters = new List<ParticleEmitter>();

        internal GraphicsDevice GraphicsDevice = null;

        internal protected ParticleSystem(GraphicsDevice graphicsDevice)
        {
            GraphicsDevice = graphicsDevice;
        }

        public void AddParticleEmitter(ParticleEmitter particleEmitter)
        {
            if (!emitters.Contains(particleEmitter))
            {
                emitters.Add(particleEmitter);
            }
        }

        public void RemoveParticleEmitter(ParticleEmitter particleEmitter)
        {
            if (emitters.Contains(particleEmitter))
            {
                emitters.Remove(particleEmitter);
            }
        }

        public void Draw()
        {
            RenderState renderState = GraphicsDevice.RenderState;


            // Enable point sprites.
            bool PointSpriteEnable = renderState.PointSpriteEnable;
            float PointSizeMax = renderState.PointSizeMax;

            // Set the alpha blend mode.
            bool AlphaBlendEnable = renderState.AlphaBlendEnable;
            BlendFunction AlphaBlendOperation = renderState.AlphaBlendOperation;

            Blend SourceBlend = renderState.SourceBlend;
            Blend DestinationBlend = renderState.DestinationBlend;

            // Set the alpha test mode.
            bool AlphaTestEnable = renderState.AlphaTestEnable;
            CompareFunction AlphaFunction = renderState.AlphaFunction;
            int ReferenceAlpha = renderState.ReferenceAlpha;

            bool DepthBufferEnable = renderState.DepthBufferEnable;
            bool DepthBufferWriteEnable = renderState.DepthBufferWriteEnable;           

            for (int i = 0; i < emitters.Count; i++)
            {
                emitters[i].Draw();
            }
            InternalDraw();

            // Enable point sprites.
            renderState.PointSpriteEnable = PointSpriteEnable;
            renderState.PointSizeMax = PointSizeMax;

            // Set the alpha blend mode.
            renderState.AlphaBlendEnable = AlphaBlendEnable;
            renderState.AlphaBlendOperation = AlphaBlendOperation;
            renderState.SourceBlend = SourceBlend;
            renderState.DestinationBlend = DestinationBlend;

            // Set the alpha test mode.
            renderState.AlphaTestEnable = AlphaTestEnable;
            renderState.AlphaFunction = AlphaFunction;
            renderState.ReferenceAlpha = ReferenceAlpha;

            // Enable the depth buffer (so particles will not be visible through
            // solid objects like the ground plane), but disable depth writes
            // (so particles will not obscure other particles).
            renderState.DepthBufferEnable = DepthBufferEnable;
            renderState.DepthBufferWriteEnable = DepthBufferWriteEnable;
        }

        internal virtual void InternalDraw()
        {
        }
    }
}
