// GUIDropZone.cpp: implementation of the GUIDropZone class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "MW4GameEd2.h"
#include "GUIDropZone.h"
#include "DrawInfo.h"
#include "GUINode.h"
#include "GameInterface.h"
#include "GroupProps.h"
#include "ObjPanelDlg.h"
#include <Adept\DropZone.hpp>
#include <Stuff\Stuff.hpp>
#include <Adept\Resource.hpp>
#include <Adept\Map.hpp>

using namespace Stuff;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

GUIDropZone::GUIDropZone(CString name,Point3D pnt):GUIObjectList(name)
{
	InMap=false;
	Build();
	SetPos(pnt);
	Name="";
	SetName(name);
	MyDropZone->instanceName=(LPCSTR)GetName();
	Check_Object(NameTable::GetInstance());
	RemoveFromMap();
	AddToMap();
	ExistEmpty=true;

	Visual=false;
	ScreenDiv=100;
}


GUIDropZone::GUIDropZone():GUIObjectList("DropZone")
{
MyDropZone=NULL;
Build();
Visual=false;
ScreenDiv=100;
InMap=false;	
}

void GUIDropZone::Build()
{
	Adept::Resource res((LPCSTR)"Misc\\DropZone\\DropZone.Instance");
	res.LoadData();
	Check_Object(Connection::Local);
	ReplicatorID base_id = Connection::Local->GetNextReplicatorID();
	MyDropZone = Cast_Object(DropZone*,Entity::CreateEntity(&res,&base_id));
	Check_Object(MyDropZone);
}	

EdGUIObject *GUIDropZone::Clone()
{
	GUIDropZone *obj=new GUIDropZone;
	obj->Copy(*this);
	return obj;
}

void GUIDropZone::Copy(GUIDropZone &obj)
{
	if(MyDropZone)
	{
	RemoveFromMap();
	delete Cast_Object(Stuff::Plug *,MyDropZone);
	MyDropZone=NULL;
	Build();
	}
	
	GUIObjectList::Copy(obj);

	Check_Object(MyDropZone);
	for(int i=0;i<GetObjectCount();i++)
	{
	LinearMatrix4D loc(GetObject(i)->GetMat());
	PlugOf<LinearMatrix4D> *plug;
	plug = new PlugOf<LinearMatrix4D>(loc);
	MyDropZone->origDropMats.Add(plug);
	}
	Verify(MyDropZone->origDropMats.GetSize()==GetObjectCount());

}

void GUIDropZone::Draw(DrawInfo &dinf)
{

if(IsHidden()) return;
SetPen(dinf);
int rad=GetScreenRadius(dinf.vinf);

CPoint pnt=dinf.vinf.DataToScreen(GetPos());
CRect rct;
rct.left=pnt.x-rad;
rct.right=pnt.x+rad;
rct.top=pnt.y-rad;
rct.bottom=pnt.y+rad;

dinf.GetDC()->MoveTo(rct.left,rct.top);
dinf.GetDC()->LineTo(rct.right,rct.bottom);

dinf.GetDC()->MoveTo(rct.left,rct.bottom);
dinf.GetDC()->LineTo(rct.right,rct.top);

dinf.GetDC()->Ellipse(&rct);

CPoint newpnt;
for(int i=0;i<GetObjectCount();i++)
	{
	newpnt=dinf.vinf.DataToScreen(GetObject(i)->GetPos());
	dinf.GetDC()->MoveTo(pnt);
	dinf.GetDC()->LineTo(newpnt);
	}

GUIObjectList::Draw(dinf);
}

void GUIDropZone::AssociateTo(DropZone *dzone)
{
	MyDropZone=NULL;
	InMap=false;
	SnapToGround=false;
	SetMat(dzone->GetLocalToParent());
	MyDropZone=dzone;
	Check_Object(MyDropZone);
	InMap=true;	
	EdGUIObject::SetName(CString((char *)MyDropZone->instanceName));
		
		GUINode *node;

		CString node_name=GetName()+"_DropPoint";
		ChainIteratorOf<DropZone::MatrixPlug *> iterator(&MyDropZone->origDropMats);
		DropZone::MatrixPlug *drop_point;
		LinearMatrix4D mat;
		while((drop_point = iterator.ReadAndNext()) != NULL)
			{	
			node=new GUINode(node_name);
			node->SetMat(drop_point->GetItem());
			AddObject(node);
			}

}

void GUIDropZone::SetName(CString &name)
{
	Check_Object(MyDropZone);
	EdGUIObject::SetName(name);
	if(InMap)
		SetEntityName(MyDropZone,GetName());
//	MyDropZone->instanceName=(LPCSTR)name;
}

EdGUIObject *GUIDropZone::AddDropPoint(Point3D &pnt)
{
	if(IsHidden()) return NULL;
	GUINode *ret=new GUINode(GetName()+"_"+"DropPoint",pnt);
	AddObject(ret);
	
	if(MyDropZone!=NULL)
	{
		Check_Object(MyDropZone);
		LinearMatrix4D loc(pnt);
		PlugOf<LinearMatrix4D> *plug;
		plug = new PlugOf<LinearMatrix4D>(loc);
		MyDropZone->origDropMats.Add(plug);
		Verify(MyDropZone->origDropMats.GetSize()==GetObjectCount());
		SyncDataToNodes();
	}
	return ret;
}


EdGUIObject *GUIDropZone::AddNodeIfSelected(Point3D &pnt,bool insert)
{
	if(IsHidden()) return NULL;
	if(!IsSelected()) return NULL;
	return AddDropPoint(pnt);
}

void GUIDropZone::SyncNodesToData()
{
	Check_Object(MyDropZone);
	int size=MyDropZone->origDropMats.GetSize();
	Verify(size==GetObjectCount());
	
	GUINode *node;		
	ChainIteratorOf<DropZone::MatrixPlug *> iterator(&MyDropZone->origDropMats);
	DropZone::MatrixPlug *drop_point;
	LinearMatrix4D mat;
	int count=0;
	while((drop_point = iterator.ReadAndNext()) != NULL)
			{	
			node=(GUINode *)GetObject(count++);
			node->SetMat(drop_point->GetItem());
			}
	
}

void GUIDropZone::DrawTag(DrawInfo &dinf, unsigned long tag_flags)
{
	if(IsHidden()) return;
	DrawTagInternal(dinf,tag_flags);
}

void GUIDropZone::SyncDataToNodes()
{
	Check_Object(MyDropZone);
	int size=MyDropZone->origDropMats.GetSize();
	Verify(size==GetObjectCount());
	
	ChainIteratorOf<DropZone::MatrixPlug *> iterator(&MyDropZone->origDropMats);
	iterator.DeletePlugs();

	SortChildren();
	for(int i=0;i<GetObjectCount();i++)
	{
		MyDropZone->origDropMats.Add(new PlugOf<LinearMatrix4D>(GetObject(i)->GetMat()));
	}
	
}

void GUIDropZone::OffsetSelection(Point3D &vct)
{
	if(IsHidden()) return;
	if(IsSelected()) EdGUIObject::OffsetBy(vct);

	if(GetObjectCount()>0)
	{
		for(int i=0;i<GetObjectCount();i++)
			GetObject(i)->OffsetSelection(vct);
	}
		SyncDataToNodes();
}

void GUIDropZone::RotateSelection(UnitQuaternion &rot)
{
	if(IsHidden()) return;
	if(IsSelected()) EdGUIObject::RotateBy(rot);

	if(GetObjectCount()>0)
	{
		for(int i=0;i<GetObjectCount();i++)
			GetObject(i)->RotateSelection(rot);
	}
	SyncDataToNodes();
}

void GUIDropZone::RemoveObject(int idx)
{
	GUIObjectList::RemoveObject(idx);
	
	Check_Object(MyDropZone);
	MyDropZone->origDropMats.Remove(Cast_Object(DropZone::MatrixPlug *,MyDropZone->origDropMats.GetNthItem(0)));
	SyncDataToNodes();
}

void GUIDropZone::RemoveFromMap()
{
if(MyDropZone && InMap)
	{
	RemoveEntityFromMap(MyDropZone);
	InMap=false;
	}
//GUIObjectList::RemoveFromMap();
}

void GUIDropZone::AddToMap()
{
if(MyDropZone && !InMap)
	{
	AddEntityToMap(MyDropZone,GetMat());
	InMap=true;
	}
//GUIObjectList::AddToMap();
}


void GUIDropZone::Select()		
{
	EdGUIObject::Select();
	for(int i=0;i<GetObjectCount();i++) GetObject(i)->Select();
}	



GUIDropZone::~GUIDropZone()
{
	DeleteAllObjects();
	if(MyDropZone)
	{
		Map::GetInstance()->RemoveChild(MyDropZone);
		RemoveEntityFromNameTable(MyDropZone);
		delete Cast_Object(Stuff::Plug *,MyDropZone);
	}
}

void GUIDropZone::SaveTextInfo(NotationFile *not_file)
{
Page *page=not_file->SetPage((char *)(LPCSTR)GetName());
page->SetEntry("Type","DropZone");
}


EdGUIObject *GUIDropZone::GetObjAtPoint(Point3D &pnt)
{
	EdGUIObject *gobj=EdGUIObject::GetObjAtPoint(pnt);
	if(gobj==NULL) gobj=GUIObjectList::GetObjAtPoint(pnt);
	return gobj;
}	

void GUIDropZone::GetExtents(Point3D *tl,Point3D *br)
{
		Point3D tl2,br2;

	EdGUIObject::GetExtents(tl,br);
	GUIObjectList::GetExtents(&tl2,&br2);
	
		tl->x=tl->x<tl2.x?tl->x:tl2.x;
		tl->z=tl->z<tl2.z?tl->z:tl2.z;
		
		br->x=br->x>br2.x?br->x:br2.x;
		br->z=br->z>br2.z?br->z:br2.z;
}

int GUIDropZone::Select(Point3D &pnt)
{
	if(IsHidden()) return 0;
	int selcount=0;
	for(int i=0;i<GetObjectCount();i++) selcount+=GetObject(i)->Select(pnt);
	return selcount+EdGUIObject::Select(pnt);
}

void GUIDropZone::AddPanel(CObjPanelDlg *pnl,UndoCommand **cmd)
{
	EdGUIObject::AddPanel(pnl,cmd);
	pnl->AddPanel(new CGroupProps(this,cmd));
}

int GUIDropZone::Select(Point3D &topleft,Point3D &bottomright)	
{
	if(IsHidden()) return 0;

	int selcount=0;
	for(int i=0;i<GetObjectCount();i++) selcount+=GetObject(i)->Select(topleft,bottomright);
	return selcount+EdGUIObject::Select(topleft,bottomright);
}
	
void GUIDropZone::OffsetBy( Point3D &pnt)
{
	if(IsHidden()) return;
	GUIObjectList::OffsetBy(pnt);
	SyncDataToNodes();
}

void GUIDropZone::RotateBy(UnitQuaternion &rot)
{
	if(IsHidden()) return;
	GUIObjectList::RotateBy(rot);
	SyncDataToNodes();
}

void GUIDropZone::UpdateMat()
{
	RemoveFromMap();
	GUIObjectList::UpdateMat();
	AddToMap();
}

