//
// App.xaml.cpp
// App クラスの実装。
//

#include "pch.h"
#include "MainPage.xaml.h"
#include "App.xaml.h"

using namespace ShootingGame;

using namespace Platform;
using namespace concurrency;
using namespace DirectX;
using namespace Windows::ApplicationModel;
using namespace Windows::ApplicationModel::Activation;
using namespace Windows::ApplicationModel::Core;
using namespace Windows::ApplicationModel::Store;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::Graphics::Display;
using namespace Windows::UI::Core;
using namespace Windows::UI::Input;
using namespace Windows::UI::ViewManagement;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Controls::Primitives;
using namespace Windows::UI::Xaml::Data;
using namespace Windows::UI::Xaml::Input;
using namespace Windows::UI::Xaml::Interop;
using namespace Windows::UI::Xaml::Media;
using namespace Windows::UI::Xaml::Navigation;

// 空のアプリケーション テンプレートについては、http://go.microsoft.com/fwlink/?LinkId=234227 を参照してください

/// <summary>
/// 単一アプリケーション オブジェクトを初期化します。これは、実行される作成したコードの
/// 最初の行であり、main() または WinMain() と論理的に等価です。
/// </summary>
App::App()
{
	InitializeComponent();
	Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending);
}

/// <summary>
/// アプリケーションがエンド ユーザーによって正常に起動されたときに呼び出されます。他のエントリ ポイントは、
/// アプリケーションが特定のファイルを開くために呼び出されたときに
/// 検索結果やその他の情報を表示するために使用されます。
/// </summary>
/// <param name="pArgs">Details about the launch request and process.</param>
void App::OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs^ pArgs)
{
	// Do not repeat app initialization when already running, just ensure that
	// the window is active
	if (pArgs->PreviousExecutionState == ApplicationExecutionState::Running)
	{
		Window::Current->Activate();
		return;
	}

	if (pArgs->PreviousExecutionState == ApplicationExecutionState::Terminated)
	{
		//TODO: 以前中断したアプリケーションから状態を読み込みます。
	}

	//// ナビゲーション コンテキストとして動作するフレームを作成し、最初のページに移動します
	//auto rootFrame = ref new Frame();
	//if (!rootFrame->Navigate(TypeName(MainPage::typeid)))
	//{
	//	throw ref new FailureException("Failed to create initial page");
	//}

	//// フレームを現在のウィンドウに配置し、アクティブであることを確認します
	//Window::Current->Content = rootFrame;
	//Window::Current->Activate();

	mainPage_ = ref new MainPage();

	// Place the frame in the current Window and ensure that it is active
	Window::Current->Content = mainPage_;
	Window::Current->Activated += ref new WindowActivatedEventHandler(this, &App::OnWindowActivationChanged);
	Window::Current->Activate();

	gameMain_ = ref new GameMain();
	gameMain_->Initialize(Window::Current->CoreWindow,mainPage_->SwapChainBackgroundPanel(),DisplayProperties::LogicalDpi);

	eventToken_ = 
		CompositionTarget::Rendering::add
		(ref new EventHandler<Object^>(this, &App::OnRendering));

  Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending);
	Resuming += ref new EventHandler<Object^>(this, &App::OnResuming);


	DisplayProperties::LogicalDpiChanged +=
		ref new DisplayPropertiesEventHandler(this, &App::OnLogicalDpiChanged);

	auto window = Window::Current->CoreWindow;
	window->SizeChanged += 
		ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &App::OnWindowSizeChanged);

	window->PointerPressed +=
		ref new TypedEventHandler<CoreWindow^, Windows::UI::Core::PointerEventArgs^>(this, &App::OnPointerPressed);

	window->PointerReleased +=
		ref new TypedEventHandler<CoreWindow^, Windows::UI::Core::PointerEventArgs^>(this, &App::OnPointerReleased);

	window->PointerMoved +=
		ref new TypedEventHandler<CoreWindow^, Windows::UI::Core::PointerEventArgs^>(this, &App::OnPointerMoved);


	timer_ = ref new BasicTimer();

}

/// <summary>
/// Invoked when application execution is being suspended.  Application state is saved
/// without knowing whether the application will be terminated or resumed with the contents
/// of memory still intact.
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
void App::OnSuspending(Object^ sender, SuspendingEventArgs^ e)
{
	//TODO: Save application state and stop any background activity
}

//----------------------------------------------------------------------
void App::OnRendering(
	_In_ Object^ sender, 
	_In_ Object^ args
	)
{
	static bool first = true;
	static float count = 1.0f;
	static float elapsed = 1.0f / 60.0f;
	static float framemax = -1.0f;
	static float framemin = 1000000.0f;
	static float delta = 1.0f / 60.0f;
	timer_->Update();
	if(!first){
		framemax = max(framemax,timer_->Delta);
		framemin = min(framemin,timer_->Delta);
		mainPage_->UpdateFrameTime(timer_->Delta,framemax,framemin,delta / count);
	} else {
		first = false;
	}
	count += 1.0f;
	delta += timer_->Delta;
	if(count > 10000000.0f)
	{
		delta = delta / count;
		count = 1.0f;
	}

	mainPage_->UpdateProcessTime(elapsed);
	gameMain_->Update(timer_->Total,timer_->Delta);
	gameMain_->Render();
	gameMain_->Present();
	elapsed = timer_->Elapsed;
}
//--------------------------------------------------------------------------------------
void App::OnWindowSizeChanged(
	_In_ CoreWindow^ sender,
	_In_ WindowSizeChangedEventArgs^ args
	)
{
	gameMain_->UpdateForWindowSizeChange();

}
//--------------------------------------------------------------------------------------
void App::OnLogicalDpiChanged(
	_In_ Object^ sender
	)
{
	gameMain_->SetDpi(DisplayProperties::LogicalDpi);
}
//--------------------------------------------------------------------------------------
void App::OnWindowActivationChanged(
	_In_ Platform::Object^ sender,
	_In_ Windows::UI::Core::WindowActivatedEventArgs^ args
	)
{
}
//--------------------------------------------------------------------------------------
void App::OnResuming(
	_In_ Platform::Object^ sender,
	_In_ Platform::Object^ args
	)
{
}

void App::OnPointerPressed(
	_In_ Windows::UI::Core::CoreWindow^ sender,
	_In_ Windows::UI::Core::PointerEventArgs^ args
	)
{
}

void App::OnPointerReleased(
	_In_ Windows::UI::Core::CoreWindow^ sender,
	_In_ Windows::UI::Core::PointerEventArgs^ args
	)
{
}

void App::OnPointerMoved(
	_In_ Windows::UI::Core::CoreWindow^ sender,
	_In_ Windows::UI::Core::PointerEventArgs^ args
	)
{
}
