//--------------------------------------------------------------------------------
//
//　ウインドウ表示プログラム
//	Author : Xu Wenjie
//	Date   : 2016-04-26
//--------------------------------------------------------------------------------
//  Update : 
//	
//--------------------------------------------------------------------------------
#include "enemy.h"
#include "game.h"
#include "goal.h"

#include "locus.h"
#include "explosion.h"
#include <time.h>
#include "KF_Precision.h"
#include "KF_BodyContact.h"
#include "score.h"

#include "sound.h"

//--------------------------------------------------------------------------------
//  定数定義
//--------------------------------------------------------------------------------
#define NUM_POLYGON ( 2 )
#define NUM_VERTEX  ( 4 )

#define TIME_TO_CREAT_ENEMY_MIN (60)
#define WAIT_CREAT_MAX (1 * 60)
#define ENEMY_WIDTH (30.0f)//ポリゴンの幅
#define ENEMY_HEIGHT (30.0f)//ポリゴンの高さ
#define ENEMY_TEXTURENAME_RED "data/TEXTURE/ball_r.png"//ファイル名
#define ENEMY_TEXTURENAME_GREEN "data/TEXTURE/ball_g.png"//ファイル名
#define ENEMY_TEXTURENAME_BLUE "data/TEXTURE/ball_b.png"//ファイル名
#define ENEMY_TEXTURENAME_YELLOW "data/TEXTURE/ball_y.png"//ファイル名
#define ENEMY_POS_LEFT (D3DXVECTOR3(30.0f, 325.0f, 0.0f))
#define ENEMY_POS_TOP (D3DXVECTOR3(640.0f, 30.0f, 0.0f))
#define ENEMY_POS_RIGHT (D3DXVECTOR3(1240.0f, 325.0f, 0.0f))
#define ENEMY_POS_BOTTOM (D3DXVECTOR3(640.0f, 690.0f, 0.0f))
#define ENEMY_SPEED_LEFT (D3DXVECTOR3(50.0f, 0.0f, 0.0f))
#define ENEMY_SPEED_TOP (D3DXVECTOR3(0.0f, 40.0f, 0.0f))//(D3DXVECTOR3(0.0f, 50.0f, 0.0f))
#define ENEMY_SPEED_RIGHT (D3DXVECTOR3(-50.0f, 0.0f, 0.0f))
#define ENEMY_SPEED_BOTTOM (D3DXVECTOR3(0.0f, -40.0f, 0.0f))//(D3DXVECTOR3(0.0f, -50.0f, 0.0f))
#define ENEMY_ANGLE (atan2(ENEMY_HEIGHT, ENEMY_WIDTH))
#define MOVE_SPEED_X (D3DXVECTOR3(1.0f,0.0f,0.0f))//四方向移動速度
#define MOVE_SPEED_Y (D3DXVECTOR3(0.0f,1.0f,0.0f))//四方向移動速度

//--------------------------------------------------------------------------------
//  構造体定義
//--------------------------------------------------------------------------------

//--------------------------------------------------------------------------------
//  プロトタイプ宣言
//--------------------------------------------------------------------------------
HRESULT MakeVerTexEnemy(LPDIRECT3DDEVICE9 pDevice);
bool CheckGoal(D3DXVECTOR3 vBallPos, D3DXVECTOR3 vGoalPos, float fRadius);

//--------------------------------------------------------------------------------
//  グローバル変数
//--------------------------------------------------------------------------------
LPDIRECT3DTEXTURE9 g_pTextureEnemy[4];//textureインターフェース
LPDIRECT3DVERTEXBUFFER9 g_pVtxBufferEnemy = NULL;//頂点バッファ管理インターフェースポインタ
ENEMY g_aEnemy[NUM_ENEMY];
int g_TimeMax = 0;
int g_Time = 0;
bool g_bUpdateTimeMax = true;

//--------------------------------------------------------------------------------
//  初期化処理
//--------------------------------------------------------------------------------
void InitEnemy(void)
{
	LPDIRECT3DDEVICE9 pDevice = GetDevice();//デバイス取得
	srand((unsigned)time(NULL));

	int nCnt = 0;
	for (nCnt = 0;nCnt < TYPE_MAX;nCnt++)
	{
		g_pTextureEnemy[nCnt] = NULL;
	}

	for (nCnt = 0; nCnt < NUM_ENEMY; nCnt++)
	{
		g_aEnemy[nCnt].pEnemyBody = new CBodyCicle;
		g_aEnemy[nCnt].pEnemyBody->Init();
		g_aEnemy[nCnt].type = TYPE_RED;
		g_aEnemy[nCnt].bUsed = false;
	}

	if (FAILED(MakeVerTexEnemy(pDevice)))//textureポインタへのポインタ
	{
		MessageBox(NULL, "MakeVerTexPlayer ERROR!!", "エラー", MB_OK | MB_ICONWARNING);
	}

	//ハードディスクからTextureの読み込み
	//※エラーチェック必須
	if (FAILED(D3DXCreateTextureFromFile(pDevice,
		ENEMY_TEXTURENAME_RED,
		&g_pTextureEnemy[0])))//textureポインタへのポインタ
	{
		MessageBox(NULL, "D3DXCreateTextureFromFile ERROR!!", "エラー", MB_OK | MB_ICONWARNING);
	}
	if (FAILED(D3DXCreateTextureFromFile(pDevice,
		ENEMY_TEXTURENAME_GREEN,
		&g_pTextureEnemy[1])))//textureポインタへのポインタ
	{
		MessageBox(NULL, "D3DXCreateTextureFromFile ERROR!!", "エラー", MB_OK | MB_ICONWARNING);
	}
	if (FAILED(D3DXCreateTextureFromFile(pDevice,
		ENEMY_TEXTURENAME_BLUE,
		&g_pTextureEnemy[2])))//textureポインタへのポインタ
	{
		MessageBox(NULL, "D3DXCreateTextureFromFile ERROR!!", "エラー", MB_OK | MB_ICONWARNING);
	}
	if (FAILED(D3DXCreateTextureFromFile(pDevice,
		ENEMY_TEXTURENAME_YELLOW,
		&g_pTextureEnemy[3])))//textureポインタへのポインタ
	{
		MessageBox(NULL, "D3DXCreateTextureFromFile ERROR!!", "エラー", MB_OK | MB_ICONWARNING);
	}
}

//--------------------------------------------------------------------------------
//  終了処理
//--------------------------------------------------------------------------------
void UninitEnemy(void)
{
	for (int nCnt = 0; nCnt < NUM_ENEMY; nCnt++)
	{
		if (g_aEnemy[nCnt].pEnemyBody != NULL)//アドレスの中身確認
		{
			g_aEnemy[nCnt].pEnemyBody->Uninit();//終了処理
			delete g_aEnemy[nCnt].pEnemyBody;//中身を削除
			g_aEnemy[nCnt].pEnemyBody = NULL;//アドレスを空にする
		}
	}

	if (g_pVtxBufferEnemy != NULL)
	{
		g_pVtxBufferEnemy->Release();
		g_pVtxBufferEnemy = NULL;
	}

	for (int nCnt = 0;nCnt < TYPE_MAX;nCnt++)
	{
		if (g_pTextureEnemy[nCnt] != NULL)
		{
			g_pTextureEnemy[nCnt]->Release();
			g_pTextureEnemy[nCnt] = NULL;
		}
	}
}

//--------------------------------------------------------------------------------
//  更新処理
//--------------------------------------------------------------------------------
void UpdateEnemy(void)
{
	//for test
	VERTEX_2D *pVtx = NULL;
	int nCnt = 0;
	int nType = 0;
	int nSide = 0;
	float fLength = 0.0f;
	float fRotation = 0.0f;
	D3DXVECTOR3 vEnemyPos;


	//enemy 生成
	if (g_bUpdateTimeMax)
	{
		g_TimeMax = rand() % WAIT_CREAT_MAX + TIME_TO_CREAT_ENEMY_MIN;
		g_Time = 0;
		g_bUpdateTimeMax = false;
	}

	g_Time++;
	if (g_Time == g_TimeMax)
	{
		g_bUpdateTimeMax = true;
		nType = rand() % 4;
		nSide = rand() % 3;

		for (nCnt = 0; nCnt < NUM_ENEMY; nCnt++)
		{
			if (g_aEnemy[nCnt].bUsed == false)
			{
				g_aEnemy[nCnt].pEnemyBody->Init();
				g_aEnemy[nCnt].pEnemyBody->SetRadius(ENEMY_HEIGHT * 0.5f);
				g_aEnemy[nCnt].pEnemyBody->cBody.SetMass(10.0f);
				g_aEnemy[nCnt].pEnemyBody->cBody.SetGravity(GRAVITY);
				g_aEnemy[nCnt].bUsed = true;

				switch (nType)
				{
				case 0:
					g_aEnemy[nCnt].type = TYPE_RED;

					switch (nSide)
					{
					case 0://right
						g_aEnemy[nCnt].pEnemyBody->cBody.SetPosCenter(ENEMY_POS_RIGHT);
						g_aEnemy[nCnt].pEnemyBody->cBody.AddForce(ENEMY_SPEED_RIGHT);
						break;
					case 1://left
						g_aEnemy[nCnt].pEnemyBody->cBody.SetPosCenter(ENEMY_POS_LEFT);
						g_aEnemy[nCnt].pEnemyBody->cBody.AddForce(ENEMY_SPEED_LEFT);
						break;
					case 2://bottom
						g_aEnemy[nCnt].pEnemyBody->cBody.SetPosCenter(ENEMY_POS_BOTTOM);
						g_aEnemy[nCnt].pEnemyBody->cBody.AddForce(ENEMY_SPEED_BOTTOM);
						break;
					default:
						break;
					}
					break;
				case 1:
					g_aEnemy[nCnt].type = TYPE_GREEN;

					switch (nSide)
					{
					case 0://left
						g_aEnemy[nCnt].pEnemyBody->cBody.SetPosCenter(ENEMY_POS_LEFT);
						g_aEnemy[nCnt].pEnemyBody->cBody.AddForce(ENEMY_SPEED_LEFT);
						break;
					case 1://top
						g_aEnemy[nCnt].pEnemyBody->cBody.SetPosCenter(ENEMY_POS_TOP);
						g_aEnemy[nCnt].pEnemyBody->cBody.AddForce(ENEMY_SPEED_TOP);
						break;
					case 2://bottom
						g_aEnemy[nCnt].pEnemyBody->cBody.SetPosCenter(ENEMY_POS_BOTTOM);
						g_aEnemy[nCnt].pEnemyBody->cBody.AddForce(ENEMY_SPEED_BOTTOM);
						break;
					default:
						break;
					}
					break;
				case 2:
					g_aEnemy[nCnt].type = TYPE_BLUE;

					switch (nSide)
					{
					case 0://right
						g_aEnemy[nCnt].pEnemyBody->cBody.SetPosCenter(ENEMY_POS_RIGHT);
						g_aEnemy[nCnt].pEnemyBody->cBody.AddForce(ENEMY_SPEED_RIGHT);
						break;
					case 1://top
						g_aEnemy[nCnt].pEnemyBody->cBody.SetPosCenter(ENEMY_POS_TOP);
						g_aEnemy[nCnt].pEnemyBody->cBody.AddForce(ENEMY_SPEED_TOP);
						break;
					case 2://left
						g_aEnemy[nCnt].pEnemyBody->cBody.SetPosCenter(ENEMY_POS_LEFT);
						g_aEnemy[nCnt].pEnemyBody->cBody.AddForce(ENEMY_SPEED_LEFT);
						break;
					default:
						break;
					}
					break;
				case 3:
					g_aEnemy[nCnt].type = TYPE_YELLOW;

					switch (nSide)
					{
					case 0://top
						g_aEnemy[nCnt].pEnemyBody->cBody.SetPosCenter(ENEMY_POS_TOP);
						g_aEnemy[nCnt].pEnemyBody->cBody.AddForce(ENEMY_SPEED_TOP);
						break;
					case 1://bottom
						g_aEnemy[nCnt].pEnemyBody->cBody.SetPosCenter(ENEMY_POS_BOTTOM);
						g_aEnemy[nCnt].pEnemyBody->cBody.AddForce(ENEMY_SPEED_BOTTOM);
						break;
					case 2://right
						g_aEnemy[nCnt].pEnemyBody->cBody.SetPosCenter(ENEMY_POS_RIGHT);
						g_aEnemy[nCnt].pEnemyBody->cBody.AddForce(ENEMY_SPEED_RIGHT);
						break;
					default:
						break;
					}
					break;
				default:
					break;
				}
				
				break;
			}
		}

	}

	g_pVtxBufferEnemy->Lock(0, 0, (void**)&pVtx, 0);

	for (nCnt = 0; nCnt < NUM_ENEMY; nCnt++)
	{
		if (g_aEnemy[nCnt].bUsed)
		{
			vEnemyPos = g_aEnemy[nCnt].pEnemyBody->cBody.GetPosCenter();
			fRotation = g_aEnemy[nCnt].pEnemyBody->cBody.GetRotation();
			fLength = sqrt(ENEMY_WIDTH * ENEMY_WIDTH + ENEMY_HEIGHT * ENEMY_HEIGHT) * 0.5f;

			//pos
			pVtx[nCnt * 4 + 0].pos = D3DXVECTOR3(vEnemyPos.x + cosf(fRotation + D3DX_PI + ENEMY_ANGLE) * fLength, vEnemyPos.y + sin(fRotation + D3DX_PI + ENEMY_ANGLE) * fLength, 0.0f);
			pVtx[nCnt * 4 + 1].pos = D3DXVECTOR3(vEnemyPos.x + cosf(fRotation - ENEMY_ANGLE) * fLength, vEnemyPos.y + sinf(fRotation - ENEMY_ANGLE) * fLength, 0.0f);
			pVtx[nCnt * 4 + 2].pos = D3DXVECTOR3(vEnemyPos.x + cosf(fRotation - D3DX_PI - ENEMY_ANGLE) * fLength, vEnemyPos.y + sinf(fRotation - D3DX_PI - ENEMY_ANGLE) * fLength, 0.0f);
			pVtx[nCnt * 4 + 3].pos = D3DXVECTOR3(vEnemyPos.x + cosf(fRotation + ENEMY_ANGLE) * fLength, vEnemyPos.y + sinf(fRotation + ENEMY_ANGLE) * fLength, 0.0f);

		}
	}



	g_pVtxBufferEnemy->Unlock();
	

	//update
	for (nCnt = 0; nCnt < NUM_ENEMY; nCnt++)
	{
		if (g_aEnemy[nCnt].bUsed)
		{
			g_aEnemy[nCnt].pEnemyBody->Update();

			switch (g_aEnemy[nCnt].type)
			{
			case TYPE_YELLOW:
				g_aEnemy[nCnt].bUsed = CheckGoal(g_aEnemy[nCnt].pEnemyBody->cBody.GetPosCenter(), GetGoal(0), g_aEnemy[nCnt].pEnemyBody->GetRadius());
				SetLocus( &g_aEnemy[ nCnt ].pEnemyBody->cBody.GetPosCenter(), 15, 50, D3DXCOLOR( 0.3f, 0.3f , 0.01f, 1.0f ) );
				SetLocus( &g_aEnemy[ nCnt ].pEnemyBody->cBody.GetPosCenter(), 7, 50, D3DXCOLOR( 0.3f, 0.3f , 0.01f, 1.0f ) );
				break;
			case TYPE_RED:
				g_aEnemy[nCnt].bUsed = CheckGoal(g_aEnemy[nCnt].pEnemyBody->cBody.GetPosCenter(), GetGoal(1), g_aEnemy[nCnt].pEnemyBody->GetRadius());
				SetLocus( &g_aEnemy[ nCnt ].pEnemyBody->cBody.GetPosCenter(), 15, 50, D3DXCOLOR( 0.3f, 0.01f , 0.01f, 1.0f ) );
				SetLocus( &g_aEnemy[ nCnt ].pEnemyBody->cBody.GetPosCenter(), 7, 50, D3DXCOLOR( 0.3f, 0.01f , 0.01f, 1.0f ) );
				break;
			case TYPE_GREEN:
				g_aEnemy[nCnt].bUsed = CheckGoal(g_aEnemy[nCnt].pEnemyBody->cBody.GetPosCenter(), GetGoal(2), g_aEnemy[nCnt].pEnemyBody->GetRadius());
				SetLocus( &g_aEnemy[ nCnt ].pEnemyBody->cBody.GetPosCenter(), 15, 50, D3DXCOLOR( 0.01f, 0.3f , 0.01f, 1.0f ) );
				SetLocus( &g_aEnemy[ nCnt ].pEnemyBody->cBody.GetPosCenter(), 7, 50, D3DXCOLOR( 0.01f, 0.3f , 0.01f, 1.0f ) );
				break;
			case TYPE_BLUE:
				g_aEnemy[nCnt].bUsed = CheckGoal(g_aEnemy[nCnt].pEnemyBody->cBody.GetPosCenter(), GetGoal(3), g_aEnemy[nCnt].pEnemyBody->GetRadius());
				SetLocus( &g_aEnemy[ nCnt ].pEnemyBody->cBody.GetPosCenter(), 15, 50, D3DXCOLOR( 0.01f, 0.01f , 0.3f, 1.0f ) );
				SetLocus( &g_aEnemy[ nCnt ].pEnemyBody->cBody.GetPosCenter(), 7, 50, D3DXCOLOR( 0.01f, 0.01f , 0.3f, 1.0f ) );
				break;
			default:
				break;
			}

			if (!g_aEnemy[nCnt].bUsed)
			{
				SetVerTexExplosion(&g_aEnemy[nCnt]);
				SetEmitter(g_aEnemy[nCnt].pEnemyBody->cBody.GetPosCenter());
				PlayOneShotSoundEffect( 3 );
				SetScore( 100 );
			}
		}

		if (g_aEnemy[nCnt].bUsed)
		{
			g_aEnemy[nCnt].bUsed = AreaContact(&g_aEnemy[nCnt].pEnemyBody->cBody, g_aEnemy[nCnt].pEnemyBody->GetRadius());

			if (!g_aEnemy[nCnt].bUsed)
			{
				SetVerTexExplosion(&g_aEnemy[nCnt]);
				//PlayOneShotSoundEffect( 3 );
			}
		}
	}
}

//--------------------------------------------------------------------------------
//  描画処理
//--------------------------------------------------------------------------------
void DrawEnemy(void)
{
	LPDIRECT3DDEVICE9 pDevice = GetDevice();//デバイス取得

	pDevice->SetStreamSource(
		0,//ストリーム番号
		g_pVtxBufferEnemy,
		0,//オフセット（開始位置）
		sizeof(VERTEX_2D));//ストライド量

	//頂点フォーマットの設定
	pDevice->SetFVF(FVF_VERTEX_2D);

	//Textureの設定
	for (int nCnt = 0; nCnt < NUM_ENEMY; nCnt++)
	{
		if (!g_aEnemy[nCnt].bUsed) { continue; }

		switch (g_aEnemy[nCnt].type)
		{
		case TYPE_RED:
			pDevice->SetTexture(0, g_pTextureEnemy[0]);
			break;
		case TYPE_GREEN:
			pDevice->SetTexture(0, g_pTextureEnemy[1]);
			break;
		case TYPE_BLUE:
			pDevice->SetTexture(0, g_pTextureEnemy[2]);
			break;
		case TYPE_YELLOW:
			pDevice->SetTexture(0, g_pTextureEnemy[3]);
			break;
		default:
			break;
		}

		//プリミティブ描画
		pDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
			nCnt * 4,//オフセット（頂点数）
			NUM_POLYGON);
	}
}

//--------------------------------------------------------------------------------
//  頂点の作成
//--------------------------------------------------------------------------------
HRESULT MakeVerTexEnemy(LPDIRECT3DDEVICE9 pDevice)
{
	if (FAILED(pDevice->CreateVertexBuffer(
		sizeof(VERTEX_2D) * NUM_VERTEX * NUM_ENEMY,//作成したい頂点バッファのサイズ
		D3DUSAGE_WRITEONLY,//頂点バッファの使用方法
		FVF_VERTEX_2D,//書かなくても大丈夫
		D3DPOOL_MANAGED,//メモリ管理方法(managed：デバイスにお任せ)
		&g_pVtxBufferEnemy,//
		NULL//
	)))
	{
		return E_FAIL;
	}

	//仮想アドレスを取得するためのポインタ
	VERTEX_2D *pVtx;
	int nCnt = 0;
	float fLength = 0.0f;
	float fRotation = 0.0f;
	D3DXVECTOR3 vEnemyPos;

	//頂点バッファをロックして、仮想アドレスを取得する
	g_pVtxBufferEnemy->Lock(
		0,//範囲
		0,//範囲
		(void**)&pVtx,//アドレスが書かれたメモ帳のアドレス
		0);

	for (nCnt = 0; nCnt < NUM_ENEMY; nCnt++)
	{
		vEnemyPos = g_aEnemy[nCnt].pEnemyBody->cBody.GetPosCenter();
		fRotation = g_aEnemy[nCnt].pEnemyBody->cBody.GetRotation();
		fLength = sqrt(ENEMY_WIDTH * ENEMY_WIDTH + ENEMY_HEIGHT * ENEMY_HEIGHT) * 0.5f;
		//頂点座標の設定（2D座標、右回り）
		pVtx[nCnt * 4 + 0].pos = D3DXVECTOR3(vEnemyPos.x + cosf(fRotation + D3DX_PI + ENEMY_ANGLE) * fLength, vEnemyPos.y + sin(fRotation + D3DX_PI + ENEMY_ANGLE) * fLength, 0.0f);
		pVtx[nCnt * 4 + 1].pos = D3DXVECTOR3(vEnemyPos.x + cosf(fRotation - ENEMY_ANGLE) * fLength, vEnemyPos.y + sinf(fRotation - ENEMY_ANGLE) * fLength, 0.0f);
		pVtx[nCnt * 4 + 2].pos = D3DXVECTOR3(vEnemyPos.x + cosf(fRotation - D3DX_PI - ENEMY_ANGLE) * fLength, vEnemyPos.y + sinf(fRotation - D3DX_PI - ENEMY_ANGLE) * fLength, 0.0f);
		pVtx[nCnt * 4 + 3].pos = D3DXVECTOR3(vEnemyPos.x + cosf(fRotation + ENEMY_ANGLE) * fLength, vEnemyPos.y + sinf(fRotation + ENEMY_ANGLE) * fLength, 0.0f);

		//rhwの設定(必ず1.0f)
		pVtx[nCnt * 4 + 0].rhw = 1.0f;
		pVtx[nCnt * 4 + 1].rhw = 1.0f;
		pVtx[nCnt * 4 + 2].rhw = 1.0f;
		pVtx[nCnt * 4 + 3].rhw = 1.0f;

		//頂点カラーの設定(0〜255の整数値)
		pVtx[nCnt * 4 + 0].color = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
		pVtx[nCnt * 4 + 1].color = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
		pVtx[nCnt * 4 + 2].color = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
		pVtx[nCnt * 4 + 3].color = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);

		//texture頂点
		pVtx[nCnt * 4 + 0].tex = D3DXVECTOR2(0.0f, 0.0f);
		pVtx[nCnt * 4 + 1].tex = D3DXVECTOR2(1.0f, 0.0f);
		pVtx[nCnt * 4 + 2].tex = D3DXVECTOR2(0.0f, 1.0f);
		pVtx[nCnt * 4 + 3].tex = D3DXVECTOR2(1.0f, 1.0f);
	}

	//仮想アドレス解放
	g_pVtxBufferEnemy->Unlock();

	return S_OK;
}

//--------------------------------------------------------------------------------
//  敵アドレス取得
//--------------------------------------------------------------------------------
//void GetEnemy(CBodyCicle *pEnemy, int nNumEnemy)
//{
//	pEnemy = g_apEnemy[nNumEnemy];
//}

ENEMY *GetEnemy(int nNumEnemy)
{
	return &g_aEnemy[nNumEnemy];
}

bool CheckGoal(D3DXVECTOR3 vBallPos, D3DXVECTOR3 vGoalPos, float fRadius)
{
	D3DXVECTOR3 vDistance = vBallPos - vGoalPos;
	float fDistance = Vector3Magnitude(vDistance);
	if (fDistance < 0.0f) { fDistance = -fDistance; }

	if (fRadius >= fDistance)
	{
		return false;
	}

	return true;
}