// MapShifterDlg.cpp : implementation file
//

#include "stdafx.h"
#include "MapShifter.h"
#include "MapShifterDlg.h"
#include "ProgDlg.h"

#include <Adept\Adept.hpp>
#include <Adept\Zone.hpp>
using namespace Stuff;


extern bool __stdcall gos_DoesFileExist( const char* FileName );

/////////////////////////////////////////////////////////////////////////////
// CMapShifterDlg dialog

CMapShifterDlg::CMapShifterDlg(CWnd* pParent /*=NULL*/)
: CDialog(CMapShifterDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CMapShifterDlg)
	// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMapShifterDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CMapShifterDlg)
	DDX_Control(pDX, IDC_MAPLIST, m_MapList);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CMapShifterDlg, CDialog)
//{{AFX_MSG_MAP(CMapShifterDlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_SHIFT, OnShift)
ON_BN_CLICKED(IDC_SELECTALL, OnSelectall)
ON_BN_CLICKED(IDC_CLEAR, OnClear)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMapShifterDlg message handlers

BOOL CMapShifterDlg::OnInitDialog()
{
	CDialog::OnInitDialog();
	
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	int mapcount=0;
	
	WIN32_FIND_DATA file_data;
	HANDLE mission_search = FindFirstFile("Content\\Missions\\*.*" , &file_data);
	
	if(mission_search != INVALID_HANDLE_VALUE)
	{
		do
		if(file_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
		{
			CString map_name(file_data.cFileName);
			if(map_name.CompareNoCase(".") && map_name.CompareNoCase(".."))
				m_MapList.AddString(file_data.cFileName);
			mapcount++;
		}
		while (FindNextFile(mission_search,&file_data));
	}
	
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CMapShifterDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting
		
		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
		
		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;
		
		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

HCURSOR CMapShifterDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CMapShifterDlg::OnCancel() 
{
	
	//	CDialog::OnCancel();
}

void CMapShifterDlg::OnOK() 
{
	
	CDialog::OnOK();
}


void ConvertMoveRectToZeroCenter (const char *filename,Stuff::Scalar xoffset,Stuff::Scalar zoffset)
{
	if (!filename)
		return;

	DWORD *file;
	DWORD filesize;
	DWORD *data;
	int numrects,i;
	struct TRect
	{
		Scalar left,right,top,bottom;
		int building;
		bool vertical;
	};
	TRect *rects;

	if(!gos_DoesFileExist(filename)) return;
	gos_GetFile(filename,(unsigned char **) &file,&filesize);
	data = file;
	numrects = *((int*) data);
	data++;
	rects = (TRect *) data;

	Stuff::FileStream stream(filename,Stuff::FileStream::WriteOnly);
	stream << numrects;

	for (i=0;i<numrects;i++)
	{
		rects->bottom += zoffset;
		rects->top += zoffset;
		rects->left += xoffset;
		rects->right += xoffset;
		stream.WriteBytes (rects,sizeof (TRect));
		rects++;
	}

	gos_Free (file);
}


void CMapShifterDlg::ProcessMap(CString mis_name)
{
CProgDlg progdlg;
progdlg.Create(IDD_PROGDLG,this);
CString tmpstr;
tmpstr="Processing ";
tmpstr+=mis_name;
progdlg.SetWindowText(mis_name);
progdlg.ShowWindow(SW_SHOW);
progdlg.m_Msg="Collecting Mission Info";
progdlg.UpdateData(FALSE);

	CString mis_path,con_path,inst_path,map_inst_path,map_name,mbounds_name,wbounds_name;
	mis_path.Format("Content\\Missions\\%s",mis_name);
	inst_path=mis_path+"\\"+mis_name+".instance";
	
	NotationFile instance_file((LPCSTR)inst_path);
	Page *page=instance_file.SetPage(mis_name);
	const char *tstr;
	tstr="";
	page->GetEntry("Map",&tstr);
	map_inst_path=tstr;
	map_name=map_inst_path;	
	map_name=map_name.Left(map_name.ReverseFind('.'));
	map_name=map_name.Mid(map_name.ReverseFind('\\')+1);

	tstr="";
	page->GetEntry("MissionBounds",&tstr);
	mbounds_name=tstr;

	tstr="";
	page->GetEntry("WarningBounds",&tstr);
	wbounds_name=tstr;


	Scalar map_size_x,map_size_z;
	GetMapSize(map_name,&map_size_x,&map_size_z);
	
	Point3D org_offset;
	org_offset.y=0.0f;
	org_offset.x=-map_size_x*0.5f;
	org_offset.z=-map_size_z*0.5f;
	
	
	
	con_path=mis_path+"\\"+mis_name+".contents";
	NotationFile contents_file((LPCSTR)con_path);
	NotationFile::PageIterator *entity_page_list = contents_file.MakePageIterator();
	Check_Object(entity_page_list);
	
	progdlg.m_Msg="Offsetting Entities";
	progdlg.UpdateData(FALSE);
	
	Page *entity_page;
	Point3D trans,newtrans;
	while ((entity_page = entity_page_list->ReadAndNext()) != NULL)
	{
		entity_page->GetEntry("Translation",&trans);
		newtrans=trans;
		newtrans+=org_offset;
		entity_page->SetEntry("Translation",newtrans);
	}
	
	contents_file.Save();
	

	progdlg.m_Msg="Offsetting Paths";
	progdlg.UpdateData(FALSE);
	//Do Paths
	CString paths_path;
	paths_path=mis_path+"\\Paths";
	
	WIN32_FIND_DATA file_data;
	HANDLE path_search = FindFirstFile(paths_path+"\\*.contents" , &file_data);
	
	if(path_search != INVALID_HANDLE_VALUE)
	{
		do
		{
			NotationFile path_file((paths_path+"\\"+file_data.cFileName));
				Page *path_page=path_file.GetPage("Path");
			Note *point_note;
			Check_Object(path_page);
				
			Page::NoteIterator *path_list=path_page->MakeNoteIterator();	
			
			while ((point_note = path_list->ReadAndNext()) != NULL)
			{
				point_note->GetEntry(&trans);
				newtrans=trans;
				newtrans+=org_offset;
				point_note->SetEntry(newtrans);
			}
			
			path_file.Save();
		}
		while (FindNextFile(path_search,&file_data));
	}

	progdlg.m_Msg="Offsetting DropZones";
	progdlg.UpdateData(FALSE);
	//Do Paths
	CString drop_path;
	paths_path=mis_path+"\\dropzones";
	
			NotationFile pstart_file((paths_path+"\\"+"PlayerStart.contents"));
			
			Page *drop_page=pstart_file.GetPage("DropPoints");
			Note *point_note;
			Check_Object(drop_page);
				
			Page::NoteIterator *drop_list=drop_page->MakeNoteIterator();	
			
			while ((point_note = drop_list->ReadAndNext()) != NULL)
			{
				point_note->GetEntry(&trans);
				newtrans=trans;
				newtrans+=org_offset;
				point_note->SetEntry(newtrans);
			}
			
			pstart_file.Save();


	progdlg.m_Msg="Offsetting Graph";
	progdlg.UpdateData(FALSE);
	//Do Graphs
CString graph_path;
	graph_path=mis_path+"\\"+mis_name+"Graph.data";
	NotationFile graph_file((LPCSTR)graph_path);
	NotationFile::PageIterator *node_list = graph_file.MakePageIterator();
	Check_Object(node_list);
	
	Page *node_page;
	while ((node_page = node_list->ReadAndNext()) != NULL)
	{
		CString page_name=node_page->GetName();
		
		if(!page_name.Left(strlen("Node")).CompareNoCase("Node"))
		{
		node_page->GetEntry("Location",&trans);
		newtrans=trans;
		newtrans+=org_offset;
		node_page->SetEntry("Location",newtrans);
		}
	}

	graph_file.Save();

	progdlg.m_Msg="Offsetting Bounds";
	progdlg.UpdateData(FALSE);
/*
//Do Bounds
CString mbounds_path,wbounds_path;
mbounds_path.Format("%s\\%s",mis_path,mbounds_name);
wbounds_path.Format("%s\\%s",mis_path,wbounds_name);

		FileStream bound_file;	
		DynamicArrayOf<Stuff::Vector2DOf<Stuff::Scalar> > bound;
	
		int i;
		if(mbounds_name.GetLength()>0 && gos_DoesFileExist((LPCSTR)mbounds_path))
		{
		bound_file.Open((LPCSTR)mbounds_path,FileStream::ReadOnly);
		MemoryStreamIO_Read(&bound_file, &bound);
		bound_file.Close();
			for (i = 0; i < bound.GetLength(); i++)
			{
			bound[i].x += org_offset.x/Adept::c_ZoneSize;
			bound[i].y += org_offset.z/Adept::c_ZoneSize;
			}

		bound_file.Open((LPCSTR)mbounds_path,FileStream::WriteOnly);
		MemoryStreamIO_Write(&bound_file, &bound);
		bound_file.Close();
		}
		
		if(wbounds_name.GetLength()>0 && gos_DoesFileExist((LPCSTR)wbounds_path))
		{
		bound_file.Open((LPCSTR)wbounds_path,FileStream::ReadOnly);
		MemoryStreamIO_Read(&bound_file, &bound);
		bound_file.Close();
		
			for (i = 0; i < bound.GetLength(); i++)
			{
			bound[i].x += org_offset.x/Adept::c_ZoneSize;
			bound[i].y += org_offset.z/Adept::c_ZoneSize;
			}

		bound_file.Open((LPCSTR)wbounds_path,FileStream::WriteOnly);
		MemoryStreamIO_Write(&bound_file, &bound);
		bound_file.Close();
		}
*/
	progdlg.m_Msg="Offsetting Rect Grid";
	progdlg.UpdateData(FALSE);
//Do Rect Grid
CString move_rect_name;
move_rect_name=mis_path+"\\"+mis_name+"RectGrid.data";		
ConvertMoveRectToZeroCenter(move_rect_name,org_offset.x,org_offset.z);

	progdlg.m_Msg="Offsetting Lights";
	progdlg.UpdateData(FALSE);
//Do Lights
CString light_path;
light_path=mis_path+"\\"+mis_name+".lights";

	NotationFile lights_file((LPCSTR)light_path);
	NotationFile::PageIterator *light_list = lights_file.MakePageIterator();
	Check_Object(light_list);
	
	Page *light_page;
	Note *pos_note;
	while ((light_page = light_list->ReadAndNext()) != NULL)
	{
	pos_note=light_page->FindNote("Position");
	if(pos_note!=NULL)
		{
		pos_note->GetEntry(&trans);
		newtrans=trans;
		newtrans+=org_offset;
		pos_note->SetEntry(newtrans);
		}
	}

	lights_file.Save();
}


void CMapShifterDlg::OnShift() 
{
	int selCount = m_MapList.GetSelCount();
	int* selected = new int [selCount];
	m_MapList.GetSelItems(selCount,selected);
	for (int i = 0; i < selCount; i++)
	{
		CString text;
		m_MapList.GetText(selected[i],text);
		ProcessMap(text);
	}
	
	delete selected;
}

void CMapShifterDlg::OnSelectall() 
{
	for (int i = 0; i < m_MapList.GetCount(); i++)
		m_MapList.SetSel(i,true);
}

void CMapShifterDlg::OnClear() 
{
	for (int i = 0; i < m_MapList.GetCount(); i++)
		m_MapList.SetSel(i,false);
}

void CMapShifterDlg::GetMapSize(CString map_name, float *xsize, float *zsize)
{
	CString map_path;
	
	map_path.Format("Content\\Maps\\%s",map_name);
	
	int rows,cols;
	
	rows=cols=0;
	
	//count rows
	CString erf_name;
	erf_name.Format("%s\\%cA.erf",map_path,'A'+rows);
	
	while(gos_DoesFileExist(erf_name))
	{
		rows++;
		erf_name.Format("%s\\%cA.erf",map_path,'A'+rows);
	}
	
	erf_name.Format("%s\\A%c.erf",map_path,'A'+cols);
	
	while(gos_DoesFileExist(erf_name))
	{
		cols++;
		erf_name.Format("%s\\A%c.erf",map_path,'A'+cols);
	}
	
	*xsize=cols*Adept::c_ZoneSize;
	*zsize=rows*Adept::c_ZoneSize;
	
}
