using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework;

using EVE.EVEShaders;
using EVE.EVEObjects;
using EVE.EVECameras;
using EVE.EVELights;

namespace EVE.EVEGpgpu
{
    public class EVEGpKernel : EVEShader
    {
        private VertexPositionTexture[] verts;
        private VertexDeclaration declaration;

        short[] indices;

        public EVEGpKernel(string asset) : base(asset) { }

        internal override void LoadContent(GraphicsDevice myDevice, ContentManager myLoader)
        {
            base.LoadContent(myDevice, myLoader);

            verts = new VertexPositionTexture[] {
            new VertexPositionTexture(new Vector3(1, -1, 0), new Vector2(1, 1)),
            new VertexPositionTexture(new Vector3(-1, -1, 0), new Vector2(0, 1)),
            new VertexPositionTexture(new Vector3(-1, 1, 0), new Vector2(0, 0)),
            new VertexPositionTexture(new Vector3(1, 1, 0), new Vector2(1, 0))
        };

            declaration = new VertexDeclaration(myDevice, VertexPositionTexture.VertexElements);

            indices = new short[] { 0, 1, 2, 2, 3, 0 };
        }

        public void PerformDebugDraw(GraphicsDevice myDevice, Texture2D inArray)
        {
            myDevice.SetRenderTarget(0, null);
            myDevice.Clear(Color.Black);
                        
            myEffect.Parameters["gTextureSlot1"].SetValue(inArray);

            SetParameters(null);
            myEffect.Begin();
            foreach (EffectPass pass in myEffect.CurrentTechnique.Passes)
            {
                pass.Begin();
                myDevice.VertexDeclaration = declaration;
                myDevice.DrawUserIndexedPrimitives
                <VertexPositionTexture>(
                    PrimitiveType.TriangleList,
                    verts,
                    0,
                    4,
                    indices,
                    0,
                    2);
                pass.End();
            }
            myEffect.End();

        }

        public Texture2D CalculateSingleKernel(GraphicsDevice myDevice, RenderTarget2D resultArray)
        {
            myDevice.SetRenderTarget(0, resultArray);
            myDevice.Clear(Color.Black);

            SetParameters(null);
            myEffect.Begin();
            foreach (EffectPass pass in myEffect.CurrentTechnique.Passes)
            {
                pass.Begin();
                myDevice.VertexDeclaration = declaration;
                myDevice.DrawUserIndexedPrimitives
                <VertexPositionTexture>(
                    PrimitiveType.TriangleList,
                    verts,
                    0,
                    4,
                    indices,
                    0,
                    2);
                pass.End();
            }
            myEffect.End();

            myDevice.SetRenderTarget(0, null);
            return resultArray.GetTexture();
        }

        public Texture2D CalculateSingleKernel(GraphicsDevice myDevice, Texture2D inArray, RenderTarget2D resultArray)
        {
            myDevice.SetRenderTarget(0,resultArray);
            myDevice.Clear(Color.Black);

            myEffect.Parameters["gTextureSlot1"].SetValue(inArray);

            SetParameters(null);
            myEffect.Begin();
            foreach (EffectPass pass in myEffect.CurrentTechnique.Passes)
            {
                pass.Begin();
                myDevice.VertexDeclaration = declaration;
                myDevice.DrawUserIndexedPrimitives
                <VertexPositionTexture>(
                    PrimitiveType.TriangleList,
                    verts,
                    0,
                    4,
                    indices,
                    0,
                    2);
                pass.End();
            }
            myEffect.End();

            myDevice.SetRenderTarget(0, null);
            return resultArray.GetTexture();            
        }

        public Texture2D CalculateSingleKernel(GraphicsDevice myDevice, Texture2D inArray1, Texture2D inArray2, RenderTarget2D resultArray)
        {
            myDevice.SetRenderTarget(0, resultArray);
            myDevice.Clear(Color.Black);

            myEffect.Parameters["gTextureSlot1"].SetValue(inArray1);
            myEffect.Parameters["gTextureSlot1"].SetValue(inArray2);

            SetParameters(null);
            myEffect.Begin();
            foreach (EffectPass pass in myEffect.CurrentTechnique.Passes)
            {
                pass.Begin();
                myDevice.VertexDeclaration = declaration;
                myDevice.DrawUserIndexedPrimitives
                <VertexPositionTexture>(
                    PrimitiveType.TriangleList,
                    verts,
                    0,
                    4,
                    indices,
                    0,
                    2);
                pass.End();
            }
            myEffect.End();

            myDevice.SetRenderTarget(0, null);
            return resultArray.GetTexture();            
        }
        /*
        internal void CalculateIterativeKernel(GraphicsDevice myDevice, Texture2D inArray, RenderTarget2D resultArray , Texture2D outArray, int iterationsNo)
        {
            for(int i=0 ; i< iterationsNo; i++)
            {
                if(i%2 == 0)
                    CalculateSingleKernel(myDevice,inArray,resultArray,outArray);
                else
                    CalculateSingleKernel(myDevice,outArray,resultArray,inArray);
            }
        }*/

    }
}
