// File: Breakable.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;

namespace BreakOut
{
	public class Breakable : Entity
	{
		private PowerUp m_oPowerUp = null;
		private Circle m_oBounds;
		private float m_fRadiusDecayRate;
		private Color m_oColor;
		private float m_fMaxRadius;
		private float m_fGrowthRate;

		public Breakable( Vector2 oLocation , float fRadius , Color oColor , float fRadiusDecayRate , PowerUp oPowerUp , float fGrowthRate )
		{
			if ( oPowerUp != null )
			{
				m_oPowerUp = oPowerUp;
				m_oPowerUp.Location = oLocation;
			}
			m_oBounds = new Circle( oLocation , fRadius );
			m_fMaxRadius = fRadius;
			m_fGrowthRate = fGrowthRate;
			m_fRadiusDecayRate = fRadiusDecayRate;
			m_oColor = oColor;
		}

		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 ];
			
			float fEdgeSize = 0.0f;
			float fSize = 1.0f;
			aVertices[ 0 ].X = -fSize;
			aVertices[ 0 ].Y = fSize;
			aVertices[ 0 ].Z = 0.0f;
			aVertices[ 0 ].Color = new Direct3D.ColorValue( 1.0f , 1.0f , 1.0f , 1.0f ).ToArgb();
			aVertices[ 0 ].Tu = fEdgeSize;
			aVertices[ 0 ].Tv = fEdgeSize;

			aVertices[ 1 ].X = -fSize;
			aVertices[ 1 ].Y = -fSize;
			aVertices[ 1 ].Z = 0.0f;
			aVertices[ 1 ].Color = new Direct3D.ColorValue( 1.0f , 1.0f , 1.0f , 1.0f ).ToArgb();
			aVertices[ 1 ].Tu = fEdgeSize;
			aVertices[ 1 ].Tv = 1.0f - fEdgeSize;

			aVertices[ 2 ].X = fSize;
			aVertices[ 2 ].Y = fSize;
			aVertices[ 2 ].Z = 0.0f;
			aVertices[ 2 ].Color = new Direct3D.ColorValue( 1.0f , 1.0f , 1.0f , 1.0f ).ToArgb();
			aVertices[ 2 ].Tu = 1.0f - fEdgeSize;
			aVertices[ 2 ].Tv = fEdgeSize;
			
			aVertices[ 3 ].X = fSize;
			aVertices[ 3 ].Y = -fSize;
			aVertices[ 3 ].Z = 0.0f;
			aVertices[ 3 ].Color = new Direct3D.ColorValue( 1.0f , 1.0f , 1.0f , 1.0f ).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 )
		{
			Direct3D.VertexBuffer oVB = oGame.GetVB( "Breakable" );
			Direct3D.Texture oTexture = oGame.GetTexture( "Breakable" );
			if ( ( oVB != null ) && ( oTexture != null ) )
			{
				oDevice.Transform.World = 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 Ball ) || ( oArgs.GetEntity( i ) is Projectile ) )
				{
					if( Degenerate() == 0 )
					{
						if ( m_oPowerUp != null )
						{
							oGame.AddPowerUp( m_oPowerUp );
							m_oPowerUp = null;
						}
						oGame.PlaySound( "Pop" );
						oGame.RemoveBreakable( this );
						oGame.AddParticleSystem( new ParticleSystem( oGame.Random , m_oBounds.Location , Color.FromArgb( 255 , 0 , 0 ) , 1.2f , 40 , Vector2.Empty , false , 0.6f , 0.5f ) );
						oGame.PlayerScore += 50;
					}
					else if ( oArgs.GetEntity( i ) is Ball )
					{
						oGame.PlayerScore += 10;
					}
				}
			}
		}

		public virtual float Update( Game oGame , float fDeltaTime )
		{
			m_oBounds.Radius = Math.Min( m_fMaxRadius , m_oBounds.Radius += ( m_fGrowthRate * fDeltaTime ) );
			return 0.0f;
		}

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

		private int Degenerate()
		{
			m_oBounds.Radius -= m_fRadiusDecayRate;
			if( m_oBounds.Radius <= 0.01f )
			{
				return 0;
			}
			return 1;
		}
	}
}
