/***************************************************************/
//
//
//		DirectX	[ fieldmap.cpp ]
//
//											Author	kazuki tanaka
//											Date	2017 5/29
/*---------------------------------------------------------------
■Update : 2017/5/29
			fieldmap.cppの作成
		   
		   2017/6/19 小暮
		    ファイル読み込んで表示する機構を追加
			ファイル構成
			(*.txt)
			vertical  
			horizonal
			スタートの向き Shellの列挙型を参照
			マップ構成

			マップはdata/MAPに入れてください
			マップ記号はfieldmap.hのTYPE列挙型を参照してください

/*---------------------------------------------------------------
	Include File
---------------------------------------------------------------*/

#include "system_component.h"

#include "fieldmap.h"

#include "gameobject.h"
#include "base.h"

#include "game_equation.h"

#include "castdx9.h"

#include <stdio.h>

#include "immortal.h"
#include "shell.h"
#include "octopus.h"
#include "start.h"
#include "keyboard.h"

#include "explosion.h"

/*---------------------------------------------------------------
	Macro Difinition
---------------------------------------------------------------*/
//フォルダパス By小暮
#define	MAPFOLDER_PATH	("data/MAP/")

/*---------------------------------------------------------------
	Const Number Difinition
---------------------------------------------------------------*/
//モデル名を、TYPEに対応するように
const char* FieldMap::MODEL_NAME[TYPE_MAX] =
{
	"" , //NONE
	"data\\MODEL\\tablesango.x" , //IMMORTAL
	"data\\MODEL\\octupas.x" , //GOAL
	"data\\MODEL\\hotate_start.x" , //START 
	"data\\MODEL\\hotate.x" , //MOVE
};

const char* FILE_NAME[] = {
	"data\\TEXTURE\\down.jpg",
	"data\\TEXTURE\\right.jpg",
	"data\\TEXTURE\\up.jpg",
	"data\\TEXTURE\\left.jpg",
};

/*----------------------------------------------------------------
	static member variable Initialize 
----------------------------------------------------------------*/

FieldMap* FieldMap::pMap = nullptr;




// FieldMap Constructor
FieldMap::FieldMap( )
	: pObj(nullptr)
	, map(nullptr)
	, vertical(0)
	, horizonal(0)
	, start(nullptr)
	, frame(0)
{

	// Menber Clear Process
	if( pMap ){
		delete pMap;
	}
	pMap = this;

	for( int j = 0; j < OBJ_PRIORITY; j++ ){
		for( int i = 0 ; i < NUM_OBJECT ; i++ )
		{
			other[j][i] = nullptr;
		}
	}

}

// FieldMap Destructor
FieldMap::~FieldMap( )
{

	// Do Nothing!!

}

// FieldMap Create Instance 
FieldMap* FieldMap::Create( void )
{

	// Create Class Instance
	return new FieldMap;

}

// FieldMap Initialize
void FieldMap::Init( const char* filename )
{

	// Initialize Process
	if( !pMap ){
		return;
	}
	

	//ファイル読み込み機能を追加　by小暮
	FILE	*fp = NULL ;	//ファイル用

	char mappath[256] = MAPFOLDER_PATH;
	strcat( mappath , filename );

	//読み込めたかチェック
	if ((fp = fopen( mappath , "r")) == NULL)
	{
		//失敗
		char	message[100] = "マップファイルが読み込めません : ";
		strcat(message , mappath );
		MessageBox( NULL , message , "ERROR[ fieldmap.cpp ]" , MB_OK | MB_ICONEXCLAMATION );
	}

	char h[16];
	fscanf(fp , "%s" , h );		
	char v[16];
	fscanf(fp , "%s" , v );
	

	vertical  = atoi(h);
	horizonal = atoi(v);
	
	char d[16];
	fscanf(fp , "%s" , d );
	int direction = atoi(d);
	
	const int size = MAP_SIZE;
	Vector2 offset( -(size*pMap->vertical)*0.5f  , size*pMap->horizonal*0.5f  );
	Vector2 objOffset( -(size*pMap->vertical)*0.5f + size * 0.5f  , size*pMap->horizonal*0.5f - size*0.5f );


	map  = new int[(vertical)*(horizonal)];
	pObj = new GameObject*[ vertical*horizonal ];

	int otherCounter = 0;
	
	Console::DebugLog( "txt data \n");
	fgetc(fp);

	for(int z = 0; z < pMap->horizonal; z++ ){
		for(int x = 0; x < pMap->vertical; x++ ){
			
			char c = fgetc(fp);
			int  fleld = atoi(&c);

			Console::DebugLog(" %d", fleld );


			//ファイル記号で作成するオブジェクトを変更
			//もし新しくオブジェクト作る場合は、ここに追加してください
			switch	(fleld){
			case IMMORTAL:
				other[0][ otherCounter ] = Model::Instance<Immortal>( MODEL_NAME[ IMMORTAL ] , Vector3( objOffset.x+size*x  ,MAP_HEIGHT,objOffset.y - size * z ), Vector3(0,0,0), Vector3(0.1,0.1,0.1));
				other[0][otherCounter]->Init();
				otherCounter++;
				break;

			case GOAL:
				other[1][ otherCounter ] = Model::Instance<Octopus>( MODEL_NAME[ GOAL ] ,  Vector3( objOffset.x+size*x  ,MAP_HEIGHT,objOffset.y - size * z ), Vector3(0,0,0),Vector3( 0.05 , 0.05 , 0.05 ));
				other[1][otherCounter]->Init();
				otherCounter++;
				break;

			case START:
				other[2][ otherCounter ]  = Model::Instance<Start>( MODEL_NAME[ START ] , Vector3( objOffset.x+size*x  ,MAP_HEIGHT,objOffset.y - size * z ), Vector3(0,0,0));
				start = other[2][otherCounter];
				dynamic_cast<Shell*>(other[2][otherCounter])->SetDirection( direction );
				other[2][otherCounter]->Init();
				otherCounter++;
				break;

			case 4:
				other[ 2][otherCounter ]= Model::Instance<Shell>( MODEL_NAME[ MOVE ] , Vector3( objOffset.x+size*x  ,MAP_HEIGHT,objOffset.y - size * z ), Vector3(0,0,0));
				other[2][otherCounter]->Init();
				dynamic_cast<Shell*>(other[2][otherCounter])->SetDirection( Shell::DIR_DOWN );
				otherCounter++;
				break;

			case 5:
				other[ 2][otherCounter ]= Model::Instance<Shell>( MODEL_NAME[ MOVE ] , Vector3( objOffset.x+size*x  ,MAP_HEIGHT,objOffset.y - size * z ), Vector3(0,0,0));
				other[2][otherCounter]->Init();
				dynamic_cast<Shell*>(other[2][otherCounter])->SetDirection( Shell::DIR_RIGHT );
				otherCounter++;		
				break;

			case 6:
				other[ 2][otherCounter ]= Model::Instance<Shell>( MODEL_NAME[ MOVE ] , Vector3( objOffset.x+size*x  ,MAP_HEIGHT,objOffset.y - size * z ), Vector3(0,0,0));
				other[2][otherCounter]->Init();
				dynamic_cast<Shell*>(other[2][otherCounter])->SetDirection( Shell::DIR_UP );
				otherCounter++;
				break;

			case 7:
				other[ 2][otherCounter ]= Model::Instance<Shell>( MODEL_NAME[ MOVE ] , Vector3( objOffset.x+size*x  ,MAP_HEIGHT,objOffset.y - size * z ), Vector3(0,0,0));
				other[2][otherCounter]->Init();
				dynamic_cast<Shell*>(other[2][otherCounter])->SetDirection( Shell::DIR_LEFT );
				otherCounter++;
				break;

			default:
				Console::DebugLog( "Error[%d] ",fleld);
				break;
			};

			Console::DebugLog("\n");

			
		}
		fgetc(fp);
	}

	fclose(fp);


	// 初期化処理
	player = PlayerControl::Create( Vector3( objOffset.x+size*(int)(vertical*0.5f)  ,MAP_HEIGHT,objOffset.y - size * (int)(horizonal*0.5f)  ) );
	player->Init();
	grid = Grid::Create( Color(0.3f,0.3f,1.0,1.0), vertical, horizonal, MAP_SIZE );
	grid->Init();
	
	select = UserInterface::Create("data\\TEXTURE\\up.jpg", 0.3f, 0.28f, Color(1,1,1,0.3), Vector3(0.65,-0.2,1) );
	select->Init();

	menu = MenuList::Create( 0.8, 0.01 );

	menu->Init( FILE_NAME, 4, Vector2( 1280, 768 ), Vector2(0.5,0.5), Color(1,1,1,0.3), 1 );

}

// FieldMap Uninitialize
void FieldMap::Uninit( void )
{

	player->Uninit();
	delete player;
	grid->Uninit();
	delete grid; 
	select->Uninit();
	//delete select;

	for( int priority = 0; priority < OBJ_PRIORITY; priority++ ){
		for( int index = 0; index < NUM_OBJECT; index++ ){
			if( other[priority][index] != NULL ){
				other[priority][index]->Uninit();
			}
		}
	}

	menu->Uninit();
	SAFE_DELETE( menu );

	// Uninitialize Process
	SAFE_DELETE_ARRAY(map)
	delete[] pObj;
	pObj = nullptr;
	delete pMap;
	pMap = nullptr;
}

// FieldMap Update
void FieldMap::Update( void )
{
	// Update Process
	if( !pMap )
		return;

	// Update Process
	for(int z = 0; z < pMap->horizonal; z++ ){
		for(int x = 0; x < pMap->vertical; x++ ){
			map[z*(vertical) + x]  = NONE;
			pObj[z*(vertical) + x] = nullptr;
		}
	}

	for( int priority = 0; priority < OBJ_PRIORITY; priority++ ){
		for( int index = 0; index < NUM_OBJECT; index++ ){
			if( other[priority][index] != NULL ){
				other[priority][index]->Update();
			}
		}
	}

	if( frame%MAP_SIZE == 0 )
		FieldCheck();

	player->Update();
	grid->Update();
	menu->Update();
	select->Update();
	select->ChangeTexture( FILE_NAME[player->GetCurrent()] );

	#ifdef _DEBUG
	if( CInputKeyboard::Access()->GetKeyTrigger(DIK_RETURN) ){
		dynamic_cast<Start*>(start)->GameStart();
	}
	#endif // _DEBUG

	if( CXboxController::Access("playerController")->GetKeyTrigger(CXboxController::XINPUT_START) ){
		dynamic_cast<Start*>(start)->GameStart();
	}

	if( dynamic_cast<Start*>(start)->GetFlag() ){
		frame++;
	}

	

}

// FieldMap Draw
void FieldMap::Draw( void )
{

	// Draw Process
	if( !pMap )
		return;



}

// FieldMap
Vector2& FieldMap::SetObject( Vector3& pos, TYPE type, GameObject* pObj )
{
	

	const int size = MAP_SIZE;
	Vector2 start( -(size*pMap->vertical)*0.5f, size*pMap->horizonal*0.5f );
	for(int z = 0; z < pMap->horizonal; z++ ){
		for(int x = 0; x < pMap->vertical; x++ ){

			Vector3 current = Vector3( start.x + size*x, MAP_HEIGHT, start.y - size*z );
			Vector3 next = Vector3( start.x + size*(x+1), MAP_HEIGHT, start.y - size*(z+1));

			Vector3 center = current + (next - current)*0.5f;

			//if( __CollisionObjectSquare<Vector3>( current, next, pos, size*0.5f ) ){
			if( __CollisionObjectSphere( &CastVec3(center), &CastVec3(pos), size*0.5f, size*0.5f )){
				if( !pMap->map[z*(pMap->vertical)+x] ){
					pMap->map[z*(pMap->vertical)+x]  = type;
					pMap->pObj[z*(pMap->vertical)+x] = pObj;
					return Vector2( x,z );
					break;
				}else{
					
					if( dynamic_cast<Base*>(pObj)->map.x < x ){

						if( dynamic_cast<Base*>(pObj)->map.y < z ){
							pObj->SetPosition( Vector3(dynamic_cast<Base*>(pObj)->prev.x-MAP_SIZE*0.5f,dynamic_cast<Base*>(pObj)->prev.y-MAP_SIZE*0.5f,dynamic_cast<Base*>(pObj)->prev.z) );
							dynamic_cast<Shell*>(pObj)->SetMoveflag(false);
						}else{
							pObj->SetPosition( Vector3(dynamic_cast<Base*>(pObj)->prev.x-MAP_SIZE*0.5f,dynamic_cast<Base*>(pObj)->prev.y,dynamic_cast<Base*>(pObj)->prev.z) );
							dynamic_cast<Shell*>(pObj)->SetMoveflag(false);
						}
					}else{

						if( dynamic_cast<Base*>(pObj)->map.y < z ){
							pObj->SetPosition( Vector3(dynamic_cast<Base*>(pObj)->prev.x,dynamic_cast<Base*>(pObj)->prev.y-MAP_SIZE*0.5f,dynamic_cast<Base*>(pObj)->prev.z) );
							dynamic_cast<Shell*>(pObj)->SetMoveflag(false);
						}else{
							pObj->SetPosition( dynamic_cast<Base*>(pObj)->prev );
							dynamic_cast<Shell*>(pObj)->SetMoveflag(false);
						}
					}

					//pObj->SetPosition( Vector3(dynamic_cast<Base*>(pObj)->map.x, dynamic_cast<Base*>(pObj)->map.y, dynamic_cast<Base*>(pObj)->prev.z ) );
					for(int z = 0; z < pMap->horizonal; z++ ){
						for(int x = 0; x < pMap->vertical; x++ ){
							Vector3 current = Vector3( start.x + size*x, MAP_HEIGHT, start.y - size*z );
							Vector3 next = Vector3( start.x + size*(x+1), MAP_HEIGHT, start.y - size*(z+1));
							Vector3 center = current + (next - current)*0.5f;
							if( __CollisionObjectSphere( &CastVec3(center), &CastVec3(pos), size*0.5f, size*0.5f )){
								if( !pMap->map[z*(pMap->vertical)+x] ){
									pMap->map[z*(pMap->vertical)+x]  = type;
									pMap->pObj[z*(pMap->vertical)+x] = pObj;	
									return Vector2( x,z );
									break;
								}
							}
						}
					}
				}
			}
		}
	}

	return Vector2( -1,-1);

}


// FieldMap
void FieldMap::PutObject( TYPE type, Base* pObj )
{

	const int size = MAP_SIZE;
	Vector2 start( -(size*pMap->vertical)*0.5f, size*pMap->horizonal*0.5f );

	for( int index = 0; index < NUM_OBJECT; index++ ){
	
		if( !pMap->other[2][index] ){
			pMap->other[2][index] = pObj;
			pMap->other[2][index] ->Init();
			if( type != -1 ){
				dynamic_cast<Shell*>(pMap->other[2][index])->SetDirection(type);
			}
			break;
		}
	}

}


// FieldMap
void FieldMap::FieldCheck( void )
{


	CDebugFont::Access()->SetRenderData( R_RENDER ,"map data \n");

	for(int z = 0; z < pMap->horizonal; z++ ){
		for(int x = 0; x < pMap->vertical; x++ ){

			CDebugFont::Access()->SetRenderData( R_RENDER ," %d", map[z*pMap->vertical+x]);

			if( map[z*pMap->vertical+x] != NONE ){
				switch( map[z*(pMap->vertical)+x] )
				{
				case IMMORTAL:
					break;
				case MOVE:
					Scissor( z, x );
					OnScissor( z, x );
					break;
				case GOAL:
					OnScissor( z, x );
					//Attack(z,x);
					break;
				default:
					break;
				}
			}
		}
		CDebugFont::Access()->SetRenderData( R_RENDER ,"\n");
	}

}

// FieldMap
int* FieldMap::GetStatus( void )
{

	return pMap->map;

}

// FieldMap
bool FieldMap::Scissor( const int& z, const int& x )
{

	/*if( x <= 1 || z <= 1 || x >= (vertical+1) || z >= (horizonal+1) ){
		return false;
	}*/

	// x axis  
	if( !(x <=  1 || x >= (vertical-2)) ){

		if( map[z*(pMap->vertical)+x] != NONE && map[z*(pMap->vertical)+x-1] != NONE && map[z*(pMap->vertical)+x-2] != NONE  && map[z*(pMap->vertical)+x-1] != IMMORTAL ){
			if( pObj[z*(pMap->vertical)+x] )
				dynamic_cast<Base*>(pObj[z*(pMap->vertical)+x])->Scissor();
			return true;
		}
		if( map[z*(pMap->vertical)+x] != NONE && map[z*(pMap->vertical)+x+1] != NONE && map[z*(pMap->vertical)+x+2] != NONE && map[z*(pMap->vertical)+x+1] != IMMORTAL ){
			if( pObj[z*(pMap->vertical)+x] )
				dynamic_cast<Base*>(pObj[(z)*(pMap->vertical)+x])->Scissor();
			return true;
		}
	}

	/// y axis
	if( !(z <= 1 || z >= (horizonal-2)) ){

		if( map[z*(pMap->vertical)+x] != NONE && map[(z-1)*(pMap->vertical)+x] != NONE && map[(z-2)*(pMap->vertical)+x] != NONE && map[(z-1)*(pMap->vertical)+x] != IMMORTAL ){
			if( pObj[z*(pMap->vertical)+x] )
				dynamic_cast<Base*>(pObj[(z)*(pMap->vertical)+x])->Scissor();
			return true;
		}
		if( map[z*(pMap->vertical)+x] != NONE && map[(z+1)*(pMap->vertical)+x] != NONE && map[(z+2)*(pMap->vertical)+x] != NONE && map[(z+1)*(pMap->vertical)+x] != IMMORTAL ){
			if( pObj[z*(pMap->vertical)+x] )
				dynamic_cast<Base*>(pObj[(z)*(pMap->vertical)+x])->Scissor();
			return true;
		}
	}
	

	return false;

}

// FieldMap
bool FieldMap::OnScissor( const int& z, const int& x )
{


	if( map[z*(pMap->vertical)+x+1] != NONE && map[z*(pMap->vertical)+x-1] != NONE && map[z*(pMap->vertical)+x-1] != IMMORTAL || map[z*(pMap->vertical)+x+1] != NONE && map[z*(pMap->vertical)+x-1] != NONE && map[z*(pMap->vertical)+x+1] != IMMORTAL ){
		dynamic_cast<Base*>(pObj[z*(pMap->vertical)+x])->OnScissor();
		return true;

	}
	if( map[(z+1)*(pMap->vertical)+x] != NONE && map[(z-1)*(pMap->vertical)+x] != NONE && map[(z+1)*(pMap->vertical)+x] != IMMORTAL ||  map[(z+1)*(pMap->vertical)+x] != NONE && map[(z-1)*(pMap->vertical)+x] != NONE && map[(z-1)*(pMap->vertical)+x] != IMMORTAL ){
		dynamic_cast<Base*>(pObj[z*(pMap->vertical)+x])->OnScissor();
		return true;
	}

	return false;


}

// FieldMap
void FieldMap::Attack( const int& z, const int& x )
{

	Vector2 objOffset( -(MAP_SIZE*pMap->vertical)*0.5f + MAP_SIZE * 0.5f  , MAP_SIZE*pMap->horizonal*0.5f - MAP_SIZE*0.5f );

	if( pObj[z*(vertical)+x+1] || pObj[z*(vertical)+x-1] || pObj[(z+1)*(vertical)+x] || pObj[(z-1)*(vertical)+x] ){
		GameObject* object = pObj[z*(vertical)+x+1];
		for( int index = 0; index < NUM_OBJECT; index++ ){
			if( other[2][index] == object ){
				Vector3 pos = other[2][index]->GetPosition();
				other[2][index]->Uninit();
				//map[z*(pMap->vertical)+x] = NONE;
				//delete other[2][index];
				//other[2][index] = nullptr;
				SetExplosion( &D3DXVECTOR3( pos.x, pos.y, pos.z ) );
			}
		}
	}

}





