//===================================================================
// Boss Main
//===================================================================

//-------------------------------------------------------------------
// include functions
//-------------------------------------------------------------------

/** IN the system folder functions */
#include_function ".\System\BossAnimation.dnh"
#include_function ".\System\Movement.dnh"
#include_function ".\System\Spell.dnh"
#include_function ".\System\Font.dnh"
/** Outside the system folder */
#include_function ".\Sound\SE\Index.dnh"
#include_function ".\__shotReplace.dnh"

//-------------------------------------------------------------------
// Variables
//-------------------------------------------------------------------

/** Enemy Hitbox */
let HitboxA = 		32;
let HitboxB =		16;
/** Spell Score */
let SpellScore =	1000000;
/** Count variable and such */
let BGCount =		0;
let MCount =		0;
/** Stage variable */
let onStage =		false;
/** Timer stuff */
let Timer = GetTimer();
let Danger = 5;
/** Main Level Count */
let Level = 2;

//-------------------------------------------------------------------
// Movement
//-------------------------------------------------------------------

/**
*	Boss movement
*
*	@param Height	( Max Height )
*	@param UD	( Up, Down )
*	@param Length	( Max Length )
*/
sub Move(){ BossMove( GetClipMinY() + 120, 10, rand( 15, 30 ) ); }
function BossMove( let Height, let UD, let Length ){
	SetAction( ACT_MOVE, 60 );
	if( GetPlayerX() < GetX() ){
		if( GetX() - Length <= GetClipMinX() ){
			SetMovePosition03( GetX() + Length + 20, rand( Height + 4 - UD, Height + UD ), 20, 2 );
		} else {
			SetMovePosition03( GetX() - Length - 20, rand( Height - UD, Height + UD ), 5, 0.75 );
		}
	} else {
		if( GetX() + Length >= GetClipMaxX ){
			SetMovePosition03( GetX() - Length - 20, rand( Height - UD, Height + UD ), 20, 2 );
		} else {
			SetMovePosition03( GetX() + Length + 20, rand( Height - UD, Height + UD ), 20, 2 );
		}
	}
}

//-------------------------------------------------------------------
// SE and Timer
//-------------------------------------------------------------------

/**
*	Delay the Sound File
*	@param SFX
*	@param Delay
*/
task PlaySEDelay( let SFX, let Delay ){
	loop( Delay ){ yield; }
	PlaySE( SFX );
}

/**
*	Loop the Sound File
*	@param SFX
*	@param TotalFrame
*	@param PlayFrame
*/
task PlaySELoop( let SFX, let TotalFrame, let PlayFrame ){
	while( TotalFrame > 0 ){
	PlaySE( SFX );
	loop( PlayFrame ){ yield; }
	TotalFrame -= PlayFrame;
	}
}

/**
*	Loop and Delay the Sound File
*	@param SFX
*	@param Delay
*	@param TotalFrame
*	@param PlayFrame
*/
task PlaySEDelayLoop( let SFX, let Delay, let TotalFrame, let PlayFrame ){
	loop( Delay ){ yield; }
	PlaySELoop( SFX, TotalFrame, PlayFrame );
}

/**
*	Play the Sound File
*	@param SFX
*/
task PlaySEEx( let SFX ){
	PlaySE( SFX );
}

task PlayTimer(){
	let PrevTimer = GetTimer();
	loop{
		Timer = GetTimer();
		loop( [ 5, 100 ][ Timer > 12 ] ){ yield; }
		if( seTimeOut != "" && Timer < 10 && PrevTimer != Timer ){
			PlaySE( [ seTimeOut, seTimeOut2 ][ Timer < Danger ] ); 
			PrevTimer = Timer;
		}
	}
}

//-------------------------------------------------------------------
// Gap Functions
//-------------------------------------------------------------------


/** 	Calculate the distance between two points in the coordinate 2D.
* 	It is a wrapper around the Hypot.
*	@param X1 
*	@param Y1 
*	@param X2 
*	@param Y2 
*	@return 
*/
function GetGapLength( let X1, let Y1, let X2, let Y2 ){ return ( ( ( X2 - X1 ) ^ 2 ) + ( ( Y2 - Y1 ) ^ 2 ) ) ^ 0.5; }

/**	Calculate the angle of the target coordinates to the coordinates 
*	from a specified point in 2D.
*	@param X1 
*	@param Y1
*	@param X2
*	@param Y2 
*	@return 
*/
function GetGapAngle( let X1, let Y1, let X2, let Y2 ){ return atan2( Y2 - Y1, X2 - X1 ); }

/**	Finds the X coordinate of the point in a particular angle, distance from a 
*	specified point in the coordinate specific 2D.
*	@param X 
*	@param Length 
*	@param Angle 
*	@return 
*/
function GetGapX( let X, let Length, let Angle ){ return X + Length * cos( Angle ); }

/**	Finds the Y coordinate of the point in a particular angle, distance from a 
*	specified point in the coordinate specific 2D.
*	@param Y 
*	@param Length 
*	@param Angle 
*	@return 
*/
function GetGapY( let Y, let Length, let Angle ){ return Y + Length * sin( Angle ); }

/**	Calculate the coordinates that particular angle, distance 
*	from a specified point in the coordinate specific 2D.
* 	It is a wrapper around the GetGapX / GetGapY.
*	@param X 
*	@param Y 
*	@param Length 
*	@param Angle 
*	@return 
*/
function GetGapPosition( let X, let Y, let Length, let Angle ){ return [ X + Length * cos( Angle ), Y + Length * sin( Angle ) ]; }

//-------------------------------------------------------------------
// Boss functions
//-------------------------------------------------------------------

/**
* 	Initialize the current boss
*/
function InitializeBoss(){
	LoadGraphic( ImageBoss );
	LoadGraphic( ImageCutIn );
	LoadGraphic( ImageBG1 );
	LoadGraphic( ImageBG2 );
	SetEnemyMarker( true );
}


/**
*	Delete current graphics in the boss
*/
function FinalizeBoss(){
	DeleteGraphic( ImageBoss );
	DeleteGraphic( ImageCutIn );
	DeleteGraphic( ImageBG1 );
	DeleteGraphic( ImageBG2 );
}

/**
*	Set boss collision
*/
function SetBossCollision(){
	SetCollisionA( GetX(), GetY(), HitboxA );
	SetCollisionB( GetX(), GetY(), HitboxB );
	yield;
}

//-------------------------------------------------------------------
// Math Function(s)
//-------------------------------------------------------------------

/**
*	Smooth out colors and stuff
*
*	@param Start	( Starting effect )
*	@param End	( Ending Effect )
*	@param Now	( Effect right now )
*	@param Limit	( Max Limit )
*/
function Smooth( let Start, let End, let Now, let Limit ){
	if( Now >= Limit || Start == End || Limit <= 0 ){ return End; }
	if( Now <= 0 ){ return Start; }
	return Start + ( End - Start ) * Now / Limit;
}

//-------------------------------------------------------------------
// Drawing functions
//-------------------------------------------------------------------

/**
*	Draw the spell image at the center
*	@param Imagefile	( Image to draw )
*/
function DrawCenter( let Imagefile ){
	SetTexture( Imagefile );
	DrawGraphic( GetCenterX(), GetCenterY() )
}

/**
*	Draw the spell image at the center with
*	rotation
*
*	@param Imagefile	( Image to draw )
*	@param Speed	( rotation speed )
*/
function DrawRotateCenter( let Imagefile, let Speed ){
	SetTexture( Imagefile );
	SetGraphicAngle( 0, 0, Speed * MCount );
	DrawGraphic( GetCenterX(), GetCenterY() );
	SetGraphicAngle( 0, 0, 0 );
	MCount ++;
}

//-------------------------------------------------------------------
// Wait function
//-------------------------------------------------------------------

/**
*	Waiting function. Used to delay bullet firing times.
*	@param Delay
*/
function Wait( let Delay ){ loop( Delay ){ yield; } }