/* App.xaml.cpp - Implementation of the application entry point
* Copyright (C) 2014 Paulo Pinto
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/

#include "pch.h"
#include "MainPage.xaml.h"
#include "Common\SuspensionManager.h"

using namespace AStarDemoWin;

using namespace Platform;
using namespace Windows::ApplicationModel;
using namespace Windows::ApplicationModel::Activation;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::UI::Xaml::Media::Animation;
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;

using namespace concurrency;

/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
App::App()
{
	InitializeComponent();
	Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending);
}

/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used when the application is launched to open a specific file, to display
/// search results, and so forth.
/// </summary>
/// <param name="e">Details about the launch request and process.</param>
void App::OnLaunched(LaunchActivatedEventArgs^ e)
{
	LaunchOrContinue(e);
}

#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
/// <summary>
/// Restores the content transitions after the app has launched.
/// </summary>
void App::RootFrame_FirstNavigated(Object^ sender, NavigationEventArgs^ e)
{
	auto rootFrame = safe_cast<Frame^>(sender);

	TransitionCollection^ newTransitions;
	if (_transitions == nullptr)
	{
		newTransitions = ref new TransitionCollection();
		newTransitions->Append(ref new NavigationThemeTransition());
	}
	else
	{
		newTransitions = _transitions;
	}

	rootFrame->ContentTransitions = newTransitions;

	rootFrame->Navigated -= _firstNavigatedToken;
}


void App::OnActivated(Windows::ApplicationModel::Activation::IActivatedEventArgs^ e)
{
	LaunchOrContinue(e);
}
#endif

/// <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>
void App::OnSuspending(Object^ sender, SuspendingEventArgs^ e)
{
	// TODO: Save application state and stop any background activity
	auto deferral = e->SuspendingOperation->GetDeferral();
	create_task(AStarDemoWin::Common::SuspensionManager::SaveAsync())
		.then([deferral]() {
		deferral->Complete(); 
	});
}

void App::LaunchOrContinue(Windows::ApplicationModel::Activation::IActivatedEventArgs^ e)
{
	auto rootFrame = dynamic_cast<Frame^>(Window::Current->Content);

	// Do not repeat app initialization when the Window already has content,
	// just ensure that the window is active
	if (rootFrame == nullptr)
	{
		// Create a Frame to act as the navigation context and associate it with
		// a SuspensionManager key
		rootFrame = ref new Frame();
		AStarDemoWin::Common::SuspensionManager::RegisterFrame(rootFrame, "appFrame");

		// Set the default language
		rootFrame->Language = Windows::Globalization::ApplicationLanguages::Languages->GetAt(0);

		if (e->PreviousExecutionState == ApplicationExecutionState::Terminated)
		{
			// TODO: Restore the saved session state only when appropriate, scheduling the
			// final launch steps after the restore is complete
			AStarDemoWin::Common::SuspensionManager::RestoreAsync();
		}

		if (rootFrame->Content == nullptr)
		{
			// If the navigation stack isn't restored, then go to the first page.
			OpenMainPage(rootFrame, e);
		}
	}
	else
	{
		if (rootFrame->Content == nullptr)
		{
			// When the navigation stack isn't restored navigate to the first page,
			// configuring the new page by passing required information as a navigation
			// parameter
			OpenMainPage(rootFrame, e);
		}
	}

#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
	if (e->Kind == ActivationKind::PickFileContinuation)
	{
		auto continuationEventArgs = dynamic_cast<IContinuationActivatedEventArgs^>(e);
		continuationManager = ref new ContinuationManager();
		if (continuationEventArgs != nullptr)
		{
			continuationManager->Continue(continuationEventArgs, rootFrame);
		}
	}
#endif

	// Place the frame in the current Window
	Window::Current->Content = rootFrame;

	// Ensure the current window is active
	Window::Current->Activate();

}

void App::OpenMainPage(Frame^ root, Windows::ApplicationModel::Activation::IActivatedEventArgs^ e)
{
	// If we are launching, then configure the new page by passing required 
	// information as a navigation parameter
	if (e->Kind == ActivationKind::Launch)
	{
		auto launchArgs = dynamic_cast<LaunchActivatedEventArgs^>(e);
		if (!root->Navigate(TypeName(MainPage::typeid), launchArgs->Arguments))
		{
			throw ref new FailureException("Failed to create initial page");
		}
	}
	else
	{
		root->Navigate(TypeName(MainPage::typeid));
	}
}
