#include "stdafx.h"

#include "TimePilot.h"
#include "DxWrapper.h"
#include "GameObject3D.h"
#include "PlayerCraft.h"
#include "Projectile.h"
#include "Missile.h"
#include "Explosion.h"
//#include "GameSettings.h"
#include "PnxUtility.h"
#include "Model.h"
#include "d3d_obj.h"
#include "ray.h"
#include "lineofsightchasing.h"
#include "LineOfSightIntercepting.h"
#include "PatternMovement.h"
#include "AssimpRenderer.h"


using namespace std;

TimePilot::TimePilot(GAMEWINDOW gw, HINSTANCE hInstance)
{



    // TODO: NUR ZUM SCHREIBEN DER SHADER, KANN WEG !
    /*
    using namespace std;
    ofstream out("g_szMaterialShader_org.fx");
    if(!out) {
        cout << "Cannot open output file.\n";
        return;
    }

    const char* str = AiToDxShaders::g_szMaterialShader.c_str();
    int len = strlen(str);
    out.write(str, len);
    out.close();
    */
    //////////////////////////////////////////////////////////////////////////


    m_GameWindow = gw;
    m_hInstance = hInstance;
    m_graphicsDeviceWasLost = false;

    Initialize();

    InitGame();
    MainLoop();

    m_Dxw->CloseDirect3D();
    m_Dxw->CloseDirectInput();
}

TimePilot::~TimePilot(void)
{
}

void TimePilot::Initialize()
{
	DxWrapper::Instance()->LogWrite("Initialize()");

    m_Dxw = DxWrapper::Instance();  

    if (GameSettings::FULLSCREEN)
    {
        m_GameWindow.Windowed   = false;
        m_GameWindow.Height     = SCREEN_HEIGHT;
        m_GameWindow.Width      = SCREEN_WIDTH;
    }
    else
    {   
        m_GameWindow.Windowed   = true;
        m_GameWindow.Width      = 1280;
        m_GameWindow.Height     = 1024;
    }


    m_Dxw->InitDirect3D(&m_GameWindow);
    m_Dxw->InitDirectInput(m_hInstance, &m_GameWindow); 
	//m_Dxw->InitFont(GameSettings::LogFontSize);

    m_Player = new PlayerCraft();		// muss ich hier schon erstellen, weil ich innerhalb von LoadGraphics() das Modell in PlayerCraft speichere

	if (GameSettings::ASSIMP_COMPARE_ASSETS && GameSettings::ASSIMP_IMPORT && GameSettings::ASSIMP_LOAD)
		m_Player2 = new PlayerCraft();

    LoadGraphics();
     
 
    m_Dxw->m_showLog = GameSettings::SHOWLOG;
    m_Dxw->m_DrawBoundingBoxes = GameSettings::RENDER_BOUNDING_BOXES;
    
    QueryPerformanceFrequency(&m_perfFrequency);        // die Genauigkeit des Timers vom System abfragen

    m_pMissile = 0;
}
    
void TimePilot::InitGame()
{
	DxWrapper::Instance()->LogWrite("InitGame()");

    m_Camera.vPos = aiVector3D(0.0f, 0.0f, GameSettings::CAMERA_DEFAULT_POSZ);
    m_Camera.vLookAt = aiVector3D(0.0f, 0.0f, 0.0f);
    m_Dxw->SetCamera(m_Camera);
    m_Dxw->SetProjection(45);

    m_Player->m_Position = CVector(0,0,0);
    m_Player->m_Velocity = CVector(0,0,0);

    m_Player->m_RotX = 0.0f;
    m_Player->m_RotY = 0.0f;
    m_Player->m_RotZ = 0.0f;

    m_Player->m_Speed = GameSettings::PLAYER_SPEED_NORMAL;

    m_Fire1Hold = false;
    m_Fire2Hold = false;
    
    m_BackGroundOffsetX = 0;
    m_BackGroundOffsetY = 0;

    m_VecProjectiles.empty();     // Speicherleck! das reicht nicht, muss die Objekte später noch deleten
    m_VecEnemies.empty();

    m_avSunLightDirection = aiVector3D(SUNLIGHT_INITIAL_DIRECTION);
	m_Player->m_AssetHelper->SetDirectionalLight(0, SUNLIGHT_COLOR, m_avSunLightDirection);

    SpawnNewEnemy(0.0f, 0.0f, 0.0f, MOV_LINEOFSIGHTCHASING);
    SpawnNewEnemy(0.0f, 0.0f, 0.0f, MOV_PATTERN);
}


void TimePilot::MainLoop()
{
    float deltaMs = 20.0;                            // Dauer des letzten Gameloops in ms
    LARGE_INTEGER startTime, endTime;            // LARGE_INTEGER ist ein struct aus DWORD LowPart, LONG HighPart, und LONGLONG QuadPart. Wenn
                                                 // Wenn das System __int64 hat, kann man einfach QuadPart auslesen, ansonsten muss man die anderen beiden benutzen

    double d = 0;

    while(HandleMessages())
    {     
        QueryPerformanceCounter(&startTime);    // startZeit speichern
               
        m_Dxw->Input(&m_InputData, m_GameWindow.hWnd);       
        Logic(deltaMs);
        Render();

        QueryPerformanceCounter(&endTime);
        
        double d = 1000.0 * (endTime.QuadPart - startTime.QuadPart) / m_perfFrequency.QuadPart;
        
        deltaMs = (float) d;

        if (deltaMs < 0.0001f)           // damit auf ganz schnellen Rechnern überhaupt noch was passiert. Double als deltaMs verwenden wär aber konsequenter
            deltaMs = 0.0001f;

        if (m_InputData.h)
            deltaMs = 0.0f;

        //cout << "d=" << d << "  deltaMs=" << deltaMs << endl;
    }
}


void TimePilot::Logic(float deltaMs)
{
    // ...take input into consideration

    DxWrapper* dxw = DxWrapper::Instance();

    if(m_InputData.up)
    {
        m_Player->m_RotY += (float)(GameSettings::PLAYER_ROT_SPEED_Y * deltaMs);
    }
    if(m_InputData.down)
    {
        m_Player->m_RotY -= (float)(GameSettings::PLAYER_ROT_SPEED_Y * deltaMs);
    }     
    if(m_InputData.left)
    {
        // drehung
		m_Player->m_RotZ -= (float)(GameSettings::PLAYER_ROT_SPEED_X * deltaMs);
        if (m_Player->m_RotZ < 0.0)
            m_Player->m_RotZ += 360.0;

        // neigung
        m_Player->m_RotY -= GameSettings::PLAYER_ROT_SPEED_JAW * deltaMs;
        if (m_Player->m_RotY < -GameSettings::PLAYER_ROT_MAX_JAW)
            m_Player->m_RotY = -GameSettings::PLAYER_ROT_MAX_JAW;
    }     
    if(m_InputData.right)
    {
        //drehung
        m_Player->m_RotZ += (float)(GameSettings::PLAYER_ROT_SPEED_X * deltaMs);
        if (m_Player->m_RotZ > 360.0)
            m_Player->m_RotZ -= 360.0;

        // neigung
        m_Player->m_RotY += GameSettings::PLAYER_ROT_SPEED_JAW * deltaMs;
        if (m_Player->m_RotY > GameSettings::PLAYER_ROT_MAX_JAW)
            m_Player->m_RotY = GameSettings::PLAYER_ROT_MAX_JAW;
    }

    // falls nicht gelenkt wird, neigung wieder zurücksetzen
    if(!m_InputData.left && !m_InputData.right)
    {
        if (m_Player->m_RotY > 0)
        {
            m_Player->m_RotY -= GameSettings::PLAYER_ROT_SPEED_JAW * deltaMs;
            if (m_Player->m_RotY < 0)
                m_Player->m_RotY = 0;
        }
        else
        {
            m_Player->m_RotY += GameSettings::PLAYER_ROT_SPEED_JAW * deltaMs;
            if (m_Player->m_RotY > 0)
                m_Player->m_RotY = 0;
        }
    }
    

    // Beschleunigung
    if(m_InputData.q && m_Player->m_Speed < GameSettings::PLAYER_SPEED_MAX)
    {
        m_Player->m_Speed += GameSettings::PLAYER_ACCELERATION * deltaMs;
        if (m_Player->m_Speed > GameSettings::PLAYER_SPEED_MAX)
            m_Player->m_Speed = GameSettings::PLAYER_SPEED_MAX;
    }
    else 
        if (!m_InputData.q && m_Player->m_Speed > GameSettings::PLAYER_SPEED_NORMAL)
    {
        m_Player->m_Speed -= GameSettings::PLAYER_ACCELERATION * deltaMs;
        if (m_Player->m_Speed < GameSettings::PLAYER_SPEED_NORMAL)
            m_Player->m_Speed = GameSettings::PLAYER_SPEED_NORMAL;

    }
    // Bremsen
    if(m_InputData.s && m_Player->m_Speed > GameSettings::PLAYER_SPEED_MIN)
    {
        m_Player->m_Speed -= GameSettings::PLAYER_ACCELERATION * deltaMs;
        if (m_Player->m_Speed < GameSettings::PLAYER_SPEED_MIN)
            m_Player->m_Speed = GameSettings::PLAYER_SPEED_MIN;
    }
    else 
        if (!m_InputData.s && m_Player->m_Speed < GameSettings::PLAYER_SPEED_NORMAL)
        {
            m_Player->m_Speed += GameSettings::PLAYER_ACCELERATION * deltaMs;
            if (m_Player->m_Speed > GameSettings::PLAYER_SPEED_NORMAL)
                m_Player->m_Speed = GameSettings::PLAYER_SPEED_NORMAL;

        }


    //fire1
    if(!m_InputData.fire1 && m_Fire1Hold)
        m_Fire1Hold = false;

    if(m_InputData.fire1 && !m_Fire1Hold)
    {
        InitProjectile(*m_Player);
        m_Fire1Hold = true;
    }


    // fire2
    if(!m_InputData.fire2 && m_Fire2Hold)
        m_Fire2Hold = false;

    if(m_InputData.fire2 && !m_Fire2Hold)
    {
        if (!m_pMissile)         
        {
            m_pMissile = new Missile(L"arrow.x", FILEPATH_RESOURCES, 0,0,0);
        }

        m_pMissile->Fire(*m_Player, *m_VecEnemies[0]);
        m_Fire2Hold = true;
        m_Dxw->LogWrite("missile created");        
    }

    // Kamera Zoom
    if(m_InputData.numMinus)
    {
        m_Camera.vPos.z -= GameSettings::CAMERA_ZOOM_SPEED * deltaMs;
    }
    if(m_InputData.numPlus)
    {
        m_Camera.vPos.z += GameSettings::CAMERA_ZOOM_SPEED * deltaMs;
    }

	AssimpRendererD3d::AssimpRenderer* assimpRenderer = AssimpRendererD3d::AssimpRenderer::Instance();

    // Sunlight Richtung ändern
    if (m_InputData.num4)
    {
        m_avSunLightDirection.x -= SUNLIGHT_SPEED * deltaMs;
        m_Player->m_AssetHelper->SetDirectionalLightDirection(0, m_avSunLightDirection);        
    }
    if (m_InputData.num6)
    {
        m_avSunLightDirection.x += SUNLIGHT_SPEED * deltaMs;
        m_Player->m_AssetHelper->SetDirectionalLightDirection(0, m_avSunLightDirection);
    }
    if (m_InputData.num8)
    {
        m_avSunLightDirection.y -= SUNLIGHT_SPEED * deltaMs;
        m_Player->m_AssetHelper->SetDirectionalLightDirection(0, m_avSunLightDirection);
    }
    if (m_InputData.num2)
    {
        m_avSunLightDirection.y += SUNLIGHT_SPEED * deltaMs;
        m_Player->m_AssetHelper->SetDirectionalLightDirection(0, m_avSunLightDirection);
    }
    if (m_InputData.num9)
    {
        m_avSunLightDirection.z += SUNLIGHT_SPEED * deltaMs;
        m_Player->m_AssetHelper->SetDirectionalLightDirection(0, m_avSunLightDirection);
    }
    if (m_InputData.num3)
    {
        m_avSunLightDirection.z -= SUNLIGHT_SPEED * deltaMs;
        m_Player->m_AssetHelper->SetDirectionalLightDirection(0, m_avSunLightDirection);
    }


    if(m_InputData.del)
    {
        m_Dxw->LogClear();
    }    
    if(m_InputData.enter)
    {
        m_Dxw->m_showLog = !m_Dxw->m_showLog;
    }


    Cycle(deltaMs);
}


void TimePilot::Cycle(float deltaMs)
{
    // cycle player
    m_Player->m_Velocity.x = m_Player->m_Speed * sin(D3DXToRadian(m_Player->m_RotZ));
    m_Player->m_Velocity.y = m_Player->m_Speed * cos(D3DXToRadian(m_Player->m_RotZ));
    m_Player->m_Position.x += m_Player->m_Velocity.x * deltaMs;
    m_Player->m_Position.y += m_Player->m_Velocity.y * deltaMs;
    m_Player->UpdatePosition(deltaMs);
    

	// cycle second asset, for debugging
	if (GameSettings::ASSIMP_COMPARE_ASSETS && m_Player2)
	{
		m_Player2->m_Position = m_Player->m_Position;
		m_Player2->m_RotX = m_Player->m_RotX;
		m_Player2->m_RotY = m_Player->m_RotY;
		m_Player2->m_RotZ = m_Player->m_RotZ;

		m_Player2->m_Position.x += 20.0f;
	}	

   
    // cycle background    
    int bgFullWidth = BACKGROUND_SLICE_WIDTH * BACKGROUND_COLS;
    int bgFullHeight = BACKGROUND_SLICE_HEIGHT * BACKGROUND_ROWS;

    m_BackGroundOffsetX += (m_Player->m_Velocity.x * deltaMs);   
    m_BackGroundOffsetY -= (m_Player->m_Velocity.y * deltaMs);
 
    // cycle enemies
    for each(EnemyCraft* e in m_VecEnemies)
    {
        e->Cycle(deltaMs);

        if (e->IsDestroyed())
            e->Spawn(0,0,0);
    }

    // cycle Projectiles
    for each(Projectile* pr in m_VecProjectiles)
    {
        if (pr->IsActive())
        {                
            pr->Cycle(deltaMs);
            std::ostringstream s(std::ostringstream::out);
            s << "m_RayRraveled=" << pr->m_RayTraveledInLastCycle << std::endl;
            strDebug1 = s.str();
        }
    }

    if (m_pMissile && m_pMissile->IsActive())
    {
        m_pMissile->Cycle(deltaMs);

        //collision check
        for each(EnemyCraft* enemy in m_VecEnemies)
        {
            if(enemy->m_BoundingBox.Intersect(m_pMissile->GetBoundingBoxOfFlightPath()))
            {
                enemy->Impact(*m_pMissile);

                if (enemy->IsDestroyed())
                    InitExplosionAt(enemy->m_Position);
            } 
        } 
    }

    // collision check
    for each(Projectile* pr in m_VecProjectiles)
    {
        if (pr->IsActive())
        {
            for each(EnemyCraft* enemy in m_VecEnemies)
            {
                if (enemy->m_BoundingBox.Intersect(pr->GetBoundingBoxOfFlightPath()))
                {          
                    enemy->Impact(*pr);

                    if (enemy->IsDestroyed())
                        InitExplosionAt(enemy->m_Position);
                }
            }            
        }
    }

    // alle Explosionen cyceln
    for each (Explosion* ex in m_VecExplosions)
    {        
         ex->Cycle(deltaMs);            
    }
           

    // camera follows player
    m_Camera.vPos.x = m_Player->m_Position.x;
    m_Camera.vPos.y = m_Player->m_Position.y;
    m_Camera.vLookAt.x = m_Player->m_Position.x;
    m_Camera.vLookAt.y = m_Player->m_Position.y;
    m_Camera.vLookAt.z = m_Player->m_Position.z;

    // der Wrapper hat seine eigene Camera, die muss noch upgedated werden
    m_Dxw->SetCamera(m_Camera);


//     std::ostringstream s(std::ostringstream::out);
//     s << "dxw->m_Camera.vPos.x=" <<  m_Dxw->m_Camera.vPos.x << "  dxw->m_Camera.vPos.y=" << m_Dxw->m_Camera.vPos.y << endl << "  dxw->m_Camera.vLookAt.x=" <<  m_Dxw->m_Camera.vLookAt.x << "  dxw->m_Camera.vLookAt.y=" <<  m_Dxw->m_Camera.vLookAt.y << endl;
//     s << "m_Player->m_Position.x=" <<  m_Player->m_Position.x << "  m_Player->m_Position.y=" <<  m_Player->m_Position.y << endl;
//     m_Dxw->WriteLog(s.str());


    Sleep(10);
}

void TimePilot::InitProjectile(const GameObject3D& shootingObj)
{   
    //std::ostringstream s(std::ostringstream::out);
    //s << " m_pShot->speedX=" << pShot->speedX << "   m_pShot->speedY=" << pShot->speedY << endl;
    //dxw->WriteLog(s.str());

    // erstmal gucken ob im array ein freier Shot ist

    
    if (!m_VecProjectiles.empty())
    {
        vector<Projectile*>::iterator itr = m_VecProjectiles.begin();
        while (itr != m_VecProjectiles.end())
        {
            Projectile* p = *itr;
            if (!p->IsActive())
            {
                 p->Fire(*m_Player, GameSettings::PROJECTILE_SPEED_PLAYER);
                 return;
            }             
            itr++;
        }
    }

    // falls noch nicht gefeuert wurde, neues Projectile erstellen
    Projectile* newProjectile = new Projectile(Projectile::GetStandardModel());

    m_VecProjectiles.push_back(newProjectile);
    newProjectile->Fire(*m_Player, GameSettings::PROJECTILE_SPEED_PLAYER);
    m_Dxw->LogWrite("new projectile created");    
}


void TimePilot::LoadGraphics()
{
    // load background slices

	if (GameSettings::RENDER_BACKGROUND)
	{
		int sliceSuffixNumber = 01;
		string fileExtension(BACKGROUND_FILEEXTENSION);
		for (int row=0; row < BACKGROUND_ROWS; row++)
		{
			for (int col=0; col < BACKGROUND_COLS; col++)
			{
				char czSuffix[4];
				if (sliceSuffixNumber < 100)
				{
					sprintf_s(czSuffix, 3, "%02d", sliceSuffixNumber);          // "%02d" heißt: 0 -> mit Nullen statt spaces auffüllen, 2 -> zwei stellen  ,  d -> dezimalzahl
				}            
				else
				{
					sprintf_s(czSuffix, 4, "%03d", sliceSuffixNumber);          // "%02d" heißt: 0 -> mit Nullen statt spaces auffüllen, 3 -> zwei stellen  ,  d -> dezimalzahl
				}
				string filename(BACKGROUND_FILENAME_PREFIX);
				filename += czSuffix + fileExtension;

				m_Dxw->LoadSprite(&m_BackGroundSprites[row][col], CA2W(filename.c_str()), FILEPATH_RESOURCES, BACKGROUND_SLICE_WIDTH, BACKGROUND_SLICE_HEIGHT,
					BACKGROUND_COLS, BACKGROUND_ROWS );

				if (m_BackGroundSprites[row][col].tex == NULL)              // falls das File nicht existiert hat, einen index zurück
				{
					col--;
				}
				sliceSuffixNumber++;
			}
		}
	}

    // schonmal die standardModels laden, damit's im Spiel nicht ruckelt
    Projectile::GetStandardModel(true);

	if (GameSettings::RENDER_ENEMIES)
		EnemyCraft::GetStandardModel();  
    
	if (GameSettings::ASSIMP_IMPORT || GameSettings::ASSIMP_SAVE)
	{
		DxWrapper::Instance()->LogWrite("...importing Assimp Data");

		SetCurrentDirectory(m_Dxw->applicationBaseDirectory);
		SetCurrentDirectory(FILEPATH_RESOURCES);
		SetCurrentDirectory(SUBDIR_MODEL_PLAYER);

		unsigned int aiImportFlags = 	aiProcess_CalcTangentSpace		| // calculate tangents and bitangents
			aiProcess_JoinIdenticalVertices | // join identical vertices
			aiProcess_Triangulate			| // triangulate n-polygons
			aiProcess_GenNormals		| // generate smooth normal vectors if not existing
			aiProcess_ConvertToLeftHanded	| // convert everything to D3D left handed space
			aiProcess_SplitLargeMeshes      | // split large, unrenderable meshes into submeshes
			aiProcess_ValidateDataStructure | 
			aiProcess_ImproveCacheLocality | 
			aiProcess_RemoveRedundantMaterials | 
			aiProcess_SortByPType|
			aiProcess_FindDegenerates | aiProcess_FindInvalidData;

		D3DXMATRIX matTransform = AssimpRendererD3d::AssimpRenderer::CreateTransformMatrix(PlayerCraft::CALIBRATION_ANGLE_PLAYER_X, PlayerCraft::CALIBRATION_ANGLE_PLAYER_Y, PlayerCraft::CALIBRATION_ANGLE_PLAYER_Z, 1.0f);
		m_Player->m_AssetHelper = AssimpRendererD3d::AssimpRenderer::Instance()->ImportAsset(CW2A(FILENAME_MODEL_PLAYER), aiImportFlags, matTransform);
		
		m_Player->m_AssetHelper->SetAmbientLight(PlayerCraft::MODIFIER_AMBIENT_LIGHT);
		m_Player->m_AssetHelper->SetSpecularShininessModificator(PlayerCraft::MODIFICATOR_SHINIESS);
		m_Player->m_AssetHelper->SetSpecularStrengthModificator(PlayerCraft::MODIFICATOR_SPECULAR_STRENGTH);

		DxWrapper::Instance()->LogWrite("... done importing Assimp Data");

		//DxWrapper::Instance()->LogWrite("-- start rotating meshes --");    
		//AssimpRendererD3d::AssimpRenderer::RotateAssetData(m_Player->m_AssetHelper, PlayerCraft::CALIBRATION_ANGLE_PLAYER_X, PlayerCraft::CALIBRATION_ANGLE_PLAYER_Y, PlayerCraft::CALIBRATION_ANGLE_PLAYER_Z);
		//DxWrapper::Instance()->LogWrite("-- done rotating meshes --");

	}

	if (GameSettings::ASSIMP_SAVE && GameSettings::ASSIMP_IMPORT)
	{
		DxWrapper::Instance()->LogWrite("...saving Assimp Data");
		SetCurrentDirectory(m_Dxw->applicationBaseDirectory);
		SetCurrentDirectory(FILEPATH_RESOURCES);
		SetCurrentDirectory(SUBDIR_MODEL_PLAYER);
		AssimpRendererD3d::AssimpRenderer::Instance()->SaveAssetToFile(*m_Player->m_AssetHelper, aiString("test.pnx"));
		DxWrapper::Instance()->LogWrite("...done saving Assimp Data");
	}

	if (GameSettings::ASSIMP_LOAD)
	{
		DxWrapper::Instance()->LogWrite("...loading AssetHelper");
		SetCurrentDirectory(m_Dxw->applicationBaseDirectory);
		SetCurrentDirectory(FILEPATH_RESOURCES);
		SetCurrentDirectory(SUBDIR_MODEL_PLAYER);

		m_Player->m_AssetHelper = AssimpRendererD3d::AssimpRenderer::Instance()->LoadAssetFromFile(aiString("test.pnx"));
		m_Player->m_AssetHelper->SetAmbientLight(PlayerCraft::MODIFIER_AMBIENT_LIGHT);
		m_Player->m_AssetHelper->SetSpecularShininessModificator(PlayerCraft::MODIFICATOR_SHINIESS);
		m_Player->m_AssetHelper->SetSpecularStrengthModificator(PlayerCraft::MODIFICATOR_SPECULAR_STRENGTH);

		DxWrapper::Instance()->LogWrite("...done loading AssetHelper");


		if (GameSettings::ASSIMP_COMPARE_ASSETS &&& GameSettings::ASSIMP_IMPORT)
		{
			m_Player2->m_AssetHelper = AssimpRendererD3d::AssimpRenderer::Instance()->LoadAssetFromFile(aiString("test.pnx"));
			m_Player2->m_AssetHelper->SetAmbientLight(PlayerCraft::MODIFIER_AMBIENT_LIGHT);
			m_Player2->m_AssetHelper->SetSpecularShininessModificator(PlayerCraft::MODIFICATOR_SHINIESS);
			m_Player2->m_AssetHelper->SetSpecularStrengthModificator(PlayerCraft::MODIFICATOR_SPECULAR_STRENGTH);
		}
	}


	if (GameSettings::ASSIMP_COMPARE_ASSETS && GameSettings::ASSIMP_LOAD && GameSettings::ASSIMP_IMPORT)
	{
		bool uneuqal = *(m_Player->m_AssetHelper) != *(m_Player2->m_AssetHelper);

		if (uneuqal)
		{
			m_Dxw->LogWrite("The Assets are NOT EQUAL !");
		}
		else
		{
			m_Dxw->LogWrite("both Assets are EQUAL !");
		}
	}

    //m_Dxw->LoadAsset(FILEPATH_MODEL_PLAYER, CW2A(FILENAME_MODEL_PLAYER));
    //Assimp::DefaultLogger::writeToStreams(new std::string message, Assimp::Logger::VERBOSE);
    //Assimp::DefaultLogger::kill();
}


void TimePilot::Render()
{   
    //if (!m_InputData.fire1)
        m_Dxw->ClearScreen();
    
    // nix malen bei Fehler (Device Lost)
    if (!m_Dxw->BeginScene())
    {
        m_graphicsDeviceWasLost = true;
        return;
    }
    else
    {
        // die Grafiken nochmal neu laden, falls das Device weg war und jetzt wieder da ist
        if (m_graphicsDeviceWasLost)
        {
            LoadGraphics();
            m_graphicsDeviceWasLost = false;
        }
    }

    //if (!m_InputData.fire1)
    //{
	if (GameSettings::RENDER_BACKGROUND)
	{
        m_Dxw->StartRender2D();
        RenderBackground();
        m_Dxw->EndRender2D();
	}
    //}

    std::ostringstream s1(std::ostream::out);
    std::ostringstream s2(std::ostream::out);
    std::ostringstream s3(std::ostream::out);
    
    //s1 << "player->PosX=" << m_Player->m_Position.x << "player->PosY=" << m_Player->m_Position.y << "player->PosZ=" << m_Player->m_Position.z << std::endl;           
    //m_Dxw->RenderTextS(s1.str(), 100,130);
    //m_Dxw->DrawTextS(s2.str(), 100,200);
    //s3 << "camera->PosX=" << m_Dxw->m_Camera.vPos.x << "camera->PosY=" << m_Dxw->m_Camera.vPos.y << "camera->PosZ=" << m_Dxw->m_Camera.vPos.z << std::endl;
    s1 << "m_avSunlightDirection=" << m_avSunLightDirection.x << ","  << m_avSunLightDirection.y << "," << m_avSunLightDirection.z << std::endl;           
    m_Dxw->RenderText(s1.str(), 600,130);
    //s3 << "camera->PosX=" << m_Dxw->m_Camera.vPos.x << "camera->PosY=" << m_Dxw->m_Camera.vPos.y << "camera->PosZ=" << m_Dxw->m_Camera.vPos.z << std::endl;
    //m_Dxw->RenderTextS(s3.str(), 100,160);
      

    // DRAWING THE PLAYER USING ASSIMP:
	if (GameSettings::ASSIMP_RENDER)
	{
		m_Player->Draw();   
		
		if (GameSettings::ASSIMP_COMPARE_ASSETS && m_Player2)
			m_Player2->Draw();
	}

    // alle Enemies rendern    
    //m_Dxw->m_DrawBoundingBoxes = false;
	if (GameSettings::RENDER_ENEMIES)
	{
		for each (EnemyCraft* e in m_VecEnemies)
		{
			e->Draw();            
			/*
			std::ostringstream s(std::ostringstream::out);
			s << "enemy->rotZ=" << e->m_RotZ << "enemy->speedX=" << e->m_Velocity.x << "\n" << "enemy->speedY=" << e->m_Velocity.y << std::endl;
			s << "enemy->pos=" << e->m_Position.x << "," << e->m_Position.y << "\n";
			m_Dxw->DrawTextS(s.str(), 100,300);
			*/
		}
	}

    
    // alle Projektile rendern    
    //m_Dxw->m_DrawBoundingBoxes =true;
    for each (Projectile* p in m_VecProjectiles)
    {
        if (p->IsActive())
        {
            p->Draw();            
            //m_Dxw->m_DrawBoundingBoxes = false;
        }
    }

    if (m_pMissile && m_pMissile->IsActive())
    {
        m_pMissile->Draw();
    }


    // alle Explosionen rendern    
    for each (Explosion* ex in m_VecExplosions)
    {
        if (ex->IsActive())
            ex->Draw();         
    }    

    m_Dxw->EndScene();
   
    m_Dxw->DisplayFrame();
}

void TimePilot::RenderBackground()
{          
    int bgFullWidth = (BACKGROUND_SLICE_WIDTH * BACKGROUND_COLS);
    int bgFullHeight = (BACKGROUND_SLICE_HEIGHT * BACKGROUND_ROWS);
    int noOfCols = SCREEN_WIDTH / BACKGROUND_SLICE_WIDTH + 2;    // warum brauch ich hier + 2?
    int noOfRows = SCREEN_HEIGHT / BACKGROUND_SLICE_HEIGHT + 2;

    int startColIndex = 0, sliceOffsetX = 0;
    int startRowIndex = 0, sliceOffsetY = 0;

    startColIndex = ((int)m_BackGroundOffsetX % bgFullWidth) / BACKGROUND_SLICE_WIDTH;
    if (startColIndex < 0)
        startColIndex += BACKGROUND_COLS;

    startRowIndex = ((int)m_BackGroundOffsetY % bgFullHeight) / BACKGROUND_SLICE_HEIGHT;
    if (startRowIndex < 0)
        startRowIndex += BACKGROUND_ROWS;

    sliceOffsetX = -(int)m_BackGroundOffsetX % BACKGROUND_SLICE_WIDTH;

    sliceOffsetY = -(int)m_BackGroundOffsetY % BACKGROUND_SLICE_HEIGHT;

    int y = - BACKGROUND_SLICE_HEIGHT + sliceOffsetY;
 
    //std::cout << "m_BackGroundOffsetX=" << m_BackGroundOffsetX << "  startColIndex=" << startColIndex << "  sliceOffsetX=" << sliceOffsetX << std::endl;
    //std::cout << "m_BackGroundOffsetY=" << m_BackGroundOffsetY << "  startRowIndex=" << startRowIndex << "  sliceOffsetY=" << sliceOffsetY << std::endl;
 
    int rowIndex = startRowIndex;
    for (int rows=0; rows < noOfRows+1; ++rows)
    {        
        int colIndex = startColIndex;   
        int x = - BACKGROUND_SLICE_WIDTH + sliceOffsetX;
        for (int cols=0; cols < noOfCols+1; ++cols)
        {
            m_Dxw->RenderSprite(&m_BackGroundSprites[rowIndex][colIndex], 1, (float)x, (float)y, 1.0f);
            x += BACKGROUND_SLICE_WIDTH;
             colIndex++;
            if (colIndex >= BACKGROUND_COLS)
                colIndex = 0;
        }
        y += BACKGROUND_SLICE_HEIGHT;
        x = sliceOffsetX;
        rowIndex++;
        if (rowIndex >= BACKGROUND_ROWS)
            rowIndex = 0;
    }    

}

void TimePilot::SpawnNewEnemy(float x, float y, float z, MovementType movementType)
{  
    EnemyCraft* newEnemy = new EnemyCraft(EnemyCraft::GetStandardModel());
    
    switch (movementType)
    {
    case MOV_LINEOFSIGHTCHASING:
        newEnemy->SetMovementLogic(new LineOfSightChasing(newEnemy, m_Player));
        break;

    case MOV_LINEOFSIGHTINTERCEPTING:
        newEnemy->SetMovementLogic(new LineOfSightChasing(newEnemy, m_Player));
        break;

    case MOV_PATTERN:
    default:
        newEnemy->SetMovementLogic(new PatternMovement(newEnemy));
        break;
    }    
    newEnemy->Spawn(x,y,z);
    newEnemy->m_RotZ = 0.0f;
    m_VecEnemies.push_back(newEnemy);
}

void TimePilot::InitExplosionAt(const CPos &position)
{
    Explosion* pNewExplosion = new Explosion();
    pNewExplosion->ExplodeAt(position);
    m_VecExplosions.push_back(pNewExplosion);
}
