// File: Projectile.cs
// Author: Sonhui Schweitzer
// Date: January 25th, 2005
// Project: CS470 Applied Software Developement Project
using System;
using System.Drawing;
using System.Collections;
using Microsoft.DirectX;
using Direct3D=Microsoft.DirectX.Direct3D;
using DirectSound=Microsoft.DirectX.DirectSound;

namespace BreakOut
{
	public class Projectile : Entity
	{
		private Circle m_oBounds;
		private Vector2 m_oVelocity;
		private ParticleSystem m_oParticleSystem;

		public Projectile( Random oRandom , Vector2 oLocation , Vector2 oVelocity )
		{
			m_oVelocity = oVelocity;
			m_oBounds = new Circle( oLocation , 0.02f );
			m_oParticleSystem = new ParticleSystem( oRandom , m_oBounds.Location , Color.FromArgb( 255 , 255 , 0 ) , 0.2f , 10 , -m_oVelocity * 0.2f , true , 0.0f , 0.1f );
		}

		public static Direct3D.VertexBuffer CreateVB( Direct3D.Device oDevice )
		{
			Direct3D.VertexBuffer oVB = new Direct3D.VertexBuffer( typeof( Direct3D.CustomVertex.PositionColoredTextured ) , 4 , oDevice , 0 , Direct3D.CustomVertex.PositionColoredTextured.Format , Microsoft.DirectX.Direct3D.Pool.Default );
			GraphicsStream oStream = oVB.Lock( 0 , 0 , 0 );
			Direct3D.CustomVertex.PositionColoredTextured[] aVertices = new Direct3D.CustomVertex.PositionColoredTextured[ 4 ];
			
			Direct3D.ColorValue oColor = new Direct3D.ColorValue( 1.0f , 1.0f , 0.0f , 1.0f );
			float fEdgeSize = 0.1f;
			float fSize = 2.5f;
			aVertices[ 0 ].X = -fSize / 2.0f;
			aVertices[ 0 ].Y = fSize;
			aVertices[ 0 ].Z = 0.0f;
			aVertices[ 0 ].Color = oColor.ToArgb();
			aVertices[ 0 ].Tu = fEdgeSize;
			aVertices[ 0 ].Tv = fEdgeSize;

			aVertices[ 1 ].X = -fSize / 2.0f;
			aVertices[ 1 ].Y = -fSize;
			aVertices[ 1 ].Z = 0.0f;
			aVertices[ 1 ].Color = oColor.ToArgb();
			aVertices[ 1 ].Tu = fEdgeSize;
			aVertices[ 1 ].Tv = 1.0f - fEdgeSize;

			aVertices[ 2 ].X = fSize / 2.0f;
			aVertices[ 2 ].Y = fSize;
			aVertices[ 2 ].Z = 0.0f;
			aVertices[ 2 ].Color = oColor.ToArgb();
			aVertices[ 2 ].Tu = 1.0f - fEdgeSize;
			aVertices[ 2 ].Tv = fEdgeSize;
			
			aVertices[ 3 ].X = fSize / 2.0f;
			aVertices[ 3 ].Y = -fSize;
			aVertices[ 3 ].Z = 0.0f;
			aVertices[ 3 ].Color = oColor.ToArgb();
			aVertices[ 3 ].Tu = 1.0f - fEdgeSize;
			aVertices[ 3 ].Tv = 1.0f - fEdgeSize;
			
			oStream.Write( aVertices );
			oVB.Unlock();
			return oVB;
		}

		public virtual void Render( Direct3D.Device oDevice , Game oGame )
		{
			m_oParticleSystem.Render( oDevice , oGame );
			Direct3D.VertexBuffer oVB = oGame.GetVB( "Projectile" );
			Direct3D.Texture oTexture = oGame.GetTexture( "Projectile" );
			if ( ( oVB != null ) && ( oTexture != null ) )
			{

				Vector2 oNormal = Vector2.Normalize( m_oVelocity );
				oDevice.Transform.World = Matrix.RotationZ( ( float )-Math.Atan( oNormal.X / oNormal.Y ) ) * Matrix.Scaling( m_oBounds.Radius , m_oBounds.Radius , 1.0f ) * Matrix.Translation( m_oBounds.Location.X , m_oBounds.Location.Y , 0.0f );

				oDevice.SetStreamSource( 0 , oVB , 0 );
				oDevice.VertexFormat = Direct3D.CustomVertex.PositionColoredTextured.Format;

				oDevice.SetTexture( 0 , oTexture );
				oDevice.RenderState.AlphaBlendEnable = true;
				oDevice.RenderState.SourceBlend = Direct3D.Blend.SourceAlpha;
				oDevice.RenderState.DestinationBlend = Direct3D.Blend.InvSourceAlpha;
				oDevice.SamplerState[ 0 ].MinFilter = Direct3D.TextureFilter.Linear;
				oDevice.SamplerState[ 0 ].MagFilter = Direct3D.TextureFilter.Linear;
				oDevice.SamplerState[ 0 ].MipFilter = Direct3D.TextureFilter.Linear;
				oDevice.TextureState[ 0 ].ColorOperation = Direct3D.TextureOperation.Modulate;
				oDevice.TextureState[ 0 ].ColorArgument1 = Direct3D.TextureArgument.TextureColor;
				oDevice.TextureState[ 0 ].ColorArgument2 = Direct3D.TextureArgument.Diffuse;
				oDevice.TextureState[ 0 ].AlphaOperation = Direct3D.TextureOperation.Modulate;
				oDevice.TextureState[ 0 ].AlphaArgument1 = Direct3D.TextureArgument.TextureColor;
				oDevice.TextureState[ 0 ].AlphaArgument2 = Direct3D.TextureArgument.Diffuse;

				oDevice.DrawPrimitives( Direct3D.PrimitiveType.TriangleStrip , 0 , 2 );
				oDevice.RenderState.AlphaBlendEnable = false;
			}
		}

		public virtual void Collide( Game oGame , CollideArgs oArgs )
		{
			for ( int i = 0 ; i < oArgs.Count ; ++i )
			{
				if ( oArgs.GetEntity( i ) is Breakable )
				{
					oGame.RemoveProjectile( this );
					oGame.PlayerScore += 1;
				}
				else if ( oArgs.GetEntity( i ) is Wall )
				{
					oGame.RemoveProjectile( this );
					oGame.PlayerScore -= 1;
				}
				oGame.AddParticleSystem( new ParticleSystem( oGame.Random , m_oBounds.Location , Color.FromArgb( 255 , 255 , 0 ) , 0.6f , 10 , Vector2.Empty , false , 0.2f , 0.18f ) );
				oGame.PlaySound( "Explode" );
			}
		}

		public virtual float Update( Game oGame , float fDeltaTime )
		{
			m_oBounds.Location += m_oVelocity * fDeltaTime;
			( ( Circle )m_oParticleSystem.GetBounds() ).Location = m_oBounds.Location;
			m_oParticleSystem.Update( oGame , fDeltaTime );
			return 0.0f;
		}

		public Bounds GetBounds()
		{
			return ( Bounds )m_oBounds;
		}
	}
}
