#include "mof/Application.hpp"
#include "mof/GraphicsDevice.hpp"
#include "mof/Window.hpp"
#include "mof/ConsoleIO.hpp"
#include "mof/Timer.hpp"
#include <stdexcept>
#include "mof/Captor.hpp"
#include "mof/InputDevice.hpp"
#include "mof/private/GraphicsDeviceImpl.hpp"
#include "mof/utilities.hpp"
#include "mof/Finalizer.hpp"

#include "mof/sound/SoundDevice.hpp"

namespace 
{
    double frame_interval_;///< フレームの間隔（ミリ秒）
    int m_nUpdatingPerFrame;
    mof::Window* m_pWindow = NULL;
	bool enable_output_frame_;
	bool enable_output_audio_;
	mof::Application::InputMode input_mode_;
}

namespace mof
{
    void Application::initialize
	( 
	    const mof::tstring& appname , 
	    int width , 
	    int height ,
	    bool fullscreen ,
	    double fps, 
	    int nUpdatingPerFrame,
		InputMode input_mode,
		bool enable_output_frame,
		bool enable_output_audio
	)
    {
		frame_interval_ = 1.0f / fps * 1000;
        m_nUpdatingPerFrame = nUpdatingPerFrame;  
		enable_output_frame_ = enable_output_frame;
		enable_output_audio_ = enable_output_audio;
		input_mode_ = input_mode;

        m_pWindow = new mof::Window( appname , width , height , fullscreen );
        mof::GraphicsDevice::initialize( m_pWindow->getHandler(), 0, width , height , fullscreen );
	    mof::InputDevice::initialize();
		mof::sound::SoundDevice::initialize(m_pWindow->getHandler(), enable_output_audio_);
 
    }
    
    void Application::finalize( )
    {
        mof::GraphicsDevice::finalize();
        mof::InputDevice::finalize();
        mof::sound::SoundDevice::finalize();
        delete m_pWindow;
    }
    
//{{{ run 
    void Application::run(scene& s) 
    {
	    MSG msg;
        ZeroMemory( &msg, sizeof(msg) );
	    mof::Timer timer;
	    mof::Timer fpsTimer;
	    int frameCount = 0;

    	mof::Captor Captor( _T("output"));
    	int sleepingTime = 0;
        for( ; ; )
        {
            while( PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE ) )
            {
				// タイマをとめる
				timer.pause();
				fpsTimer.pause();
	    		if( msg.message == WM_QUIT )return;
	    		GetMessage( &msg , NULL , 0 , 0 );
                TranslateMessage( &msg );
                DispatchMessage( &msg );
            }
			// タイマが止まっていれば、再開 
			timer.start();
			fpsTimer.start();
		
		    for( int i = 0 ; i < m_nUpdatingPerFrame ; i++ )s.update();//シーンの処理

		
		    mof::GraphicsDevice::beginScene();
		    s.draw();//シーンの描画
		    if (enable_output_frame_) Captor.capture();
		    mof::GraphicsDevice::endScene();

		    //FPSの計測
		    double true_past_time = timer.getTime();
			double past_time = frame_interval_ * (frameCount + 1);
		    if(past_time > true_past_time) {
			    Sleep(static_cast<int>(past_time - true_past_time));
			    sleepingTime += past_time - true_past_time;
		    }
		    
		    //timer.reset();
		    
		    if(++frameCount % 500 == 0)
		    {
			    float fps = 500.0f / static_cast<float>(fpsTimer.getTime() - sleepingTime) * 1000;
			    fpsTimer.reset();
			    sleepingTime = 0;
			    DEBUG_PRINT( "FPS --- " << fps );
			}
	    } // for
		

    } 
//}}}
	
    void Application::quit( )
    {
	    PostQuitMessage(0);
    }


	Application::InputMode Application::input_mode() {
		return input_mode_;
	}
}


