/* AStarViewModel.cpp - ViewModel for the common UI code between store and phone
* 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 <sstream>

#include "Map.h"
#include "MapWidget.h"
#include "WindowsRender.h"

#include "AStarViewModel.h"

using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::Storage;
using namespace Windows::UI::Core;
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::Media;
using namespace Windows::UI::Xaml::Navigation;
using namespace concurrency;


ViewModel::AStarViewModel::AStarViewModel()
{
	dxRender = nullptr;
	GoButtonEnabled = false;

	TimeSpan ts;
	ts.Duration = 10000; // refresh rate

	dispatcherTimer = ref new DispatcherTimer();
	dispatcherTimer->Tick += ref new EventHandler<Object^>(this, &ViewModel::AStarViewModel::dispatcherTimer_Tick);
	dispatcherTimer->Interval = ts;

	Window::Current->CoreWindow->GetForCurrentThread()->Activated += ref new TypedEventHandler<CoreWindow ^, WindowActivatedEventArgs ^>(this, &ViewModel::AStarViewModel::OnActivated);
}


ViewModel::AStarViewModel::~AStarViewModel()
{
}


void ViewModel::AStarViewModel::LoadFile(StorageFile^ file)
{
	create_task(FileIO::ReadTextAsync(file)).then([this](String^ data)
	{
		std::wstring str(data->Data());
		std::wistringstream buffer(str);

		if (widget.loadMap(buffer))
		{
			WindowsRender render(dxRender);
			widget.paint(render);

			GoButtonEnabled = true;
			NotifyPropertyChanged("GoButtonEnabled");
		}
	});
}

void ViewModel::AStarViewModel::dispatcherTimer_Tick(Platform::Object^ sender, Platform::Object^ e)
{
	WindowsRender render(dxRender);
	widget.paint(render);

	Window::Current->CoreWindow->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Low,
		ref new Windows::UI::Core::DispatchedHandler([this]() {
		NotifyPropertyChanged("MapImage");
	}));
}


void ViewModel::AStarViewModel::OnActivated(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowActivatedEventArgs^ e)
{
	if (e->WindowActivationState == CoreWindowActivationState::Deactivated)
	{
		dispatcherTimer->Stop();
	}
	else if (widget.is_running())
	{
		dispatcherTimer->Start();
	}
}

void ViewModel::AStarViewModel::ClearMap_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
	widget.clearMap();
}

void  ViewModel::AStarViewModel::Search_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
	widget.startSearch();
	dispatcherTimer->Start();
}

void ViewModel::AStarViewModel::Page_SizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e)
{
	dxRender = ref new ImageSourceImplementation::ImageSourceImpl(static_cast<int>(e->NewSize.Width), static_cast<int>(e->NewSize.Height), true);
	MapImage = dxRender;

	NotifyPropertyChanged("MapImage");
}

void ViewModel::AStarViewModel::NotifyPropertyChanged(Platform::String^ prop)
{
	auto args = ref new PropertyChangedEventArgs(prop);
	PropertyChanged(this, args);
}


void ViewModel::AStarViewModel::MapImage_DoubleTapped(Platform::Object^ sender, Windows::UI::Xaml::Input::DoubleTappedRoutedEventArgs^ e)
{
	WindowsRender render(dxRender);
	auto point = e->GetPosition(nullptr);
	widget.mouseDoubleClickEvent(point.X, point.Y);
	e->Handled = true;
	widget.paint(render);
}