#include "NTForm.h"
#include "NTScreen.h"
#include "NTEvent.h"

namespace NTCurses {

NTForm::NTForm() : NTWidget::NTWidget() {}
NTForm::NTForm( NT::NTString id ) : NTWidget::NTWidget( id ) {}
NTForm::NTForm( NTWidget *parent ) : NTWidget::NTWidget( parent ) {}
NTForm::NTForm( NT::NTString id , NTWidget *parent ) : NTWidget::NTWidget( id , parent ) {}

void NTForm::Init( void ) {
	NTWidget::Init();
	bExit = false;
}

void NTForm::Deinit( void ) {
	NTWidget::Deinit();
}

void NTForm::Create( void ) {
	if (IsCreated()) return;	// already created
	// override original Create, even if it has parent, curses created
	oCurses=new NTCurses( uX , uY , uWidth , uHeight , true );
}

void NTForm::Destroy( void ) {
	if (!IsCreated()) return;	// already destroyed
	// override original Destroy, curses will always exist in forms (because of panels)
	delete oCurses;
	oCurses = NULL;
}

int NTForm::DoModal( void ) {
	NTScreen *scr = NTGetGlobalScreen();
	Draw();
	scr->SetDirty();
	HandleEvents();
	DrawChildWidgets();
	while (!bExit) {
		int ch = scr->GetChar();
		if (ch==KEY_MOUSE) {
			PushEvent( NTMouseEvent( scr->GetMouseEvent() ) );
		} else if (ch!=ERR) {
			PushEvent( NTKeyEvent( ch ) );
		}
		HandleEvents();
		DrawChildWidgets();
	}
	return iModalRetval;
}

void NTForm::HandleKeyEvent( int keycode ) {
	switch (keycode) {
	/*
	case 27:
		PushEvent( NTModalExitEvent( 0 ) );
		break;
	*/
	default:
		PushActiveChildEvent( NTKeyEvent( keycode ) );
		break;
	}
}

bool NTForm::IsCoordinateInRect( unsigned int x , unsigned int y , unsigned int x1 , unsigned int y1 , unsigned int width , unsigned int height ) {
	if (x<x1) return false;
	if (y<y1) return false;
	if (x>=x1+width) return false;
	if (y>=y1+height) return false;
	return true;
}

void NTForm::HandleMouseEvent( int mx , int my , int mz , unsigned int bstate ) {
	// NTWidget::HandleMouseEvent( mx , my , mz , bstate );
	// is in the form
	mx=mx-uX;
	my=my-uY;
	if (mx<0 || my<0) return;
	if (mx>(int)uWidth) return;
	if (my>(int)uHeight) return;

	if (bstate&BUTTON1_CLICKED) {
		// now check childs
		unsigned int i;
		unsigned int len;
		NTWidget *newactive = NULL;
		len = oChilds.size();

		for (i=0;i<len;i++) {
			NTWidget *item = oChilds.at(i);
			if (!item->GetEnabled()) continue;
			if (!IsCoordinateInRect( mx , my ,
				item->GetX(),
				item->GetY(),
				item->GetWidth(),
				item->GetHeight() ) ) continue;
			newactive = item;
			break;
		}
		if (newactive) {
			SetActiveChild( newactive );
			newactive->PushEvent( NTMouseEvent( mx , my , mz , bstate ) );
		}
	}
}

void NTForm::HandleEvent( NTEvent evt ) {
	switch (evt.event_type) {
	default:
		NTWidget::HandleEvent( evt );
		break;
	case NT_EVENT_NEXT_NODE_FOCUS:
		{
			int widgetnum = GetActiveChildWidgetNumber();
			if (widgetnum<0) break;
			oChilds.at(widgetnum)->HandleLostFocusEvent();
			widgetnum = GetNextEnabledChildWidgetNumber( widgetnum );
			if (widgetnum<0) break;
			oChilds.at(widgetnum)->HandleGotFocusEvent();
		}
		break;
	case NT_EVENT_PREV_NODE_FOCUS:
		{
			int widgetnum = GetActiveChildWidgetNumber();
			if (widgetnum<0) break;
			oChilds.at(widgetnum)->HandleLostFocusEvent();
			widgetnum = GetPrevEnabledChildWidgetNumber( widgetnum );
			if (widgetnum<0) break;
			oChilds.at(widgetnum)->HandleGotFocusEvent();
		}
		break;
	case NT_EVENT_KEYPRESS:
		// fprintf( stderr , "%d\n" , evt.event_data.keycode );
		HandleKeyEvent( evt.event_data.keycode );
	}	
}

void NTForm::HandleModalExitEvent( int exitcode ) {
	bExit = true;
	iModalRetval = exitcode;
}

void NTForm::HandleEvents( void ) {
	HandleChildEvents();
	while (HasEvent()) {
		NTEvent evt = PopEvent();
		switch (evt.event_type) {
		case NT_EVENT_MODAL_EXIT:
			HandleModalExitEvent( evt.event_data.modal_exit );
			break;
		default:
			HandleEvent( evt );
		}
		HandleChildEvents();
	}
}

void NTForm::SetTitle( NT::NTString t ) {
	sTitle = t;
}

NT::NTString NTForm::GetTitle( void  ) {
	return sTitle;
}

unsigned int NTForm::GetRelativeX( void ) {
	// forms doesnt have relative coords
	return 0;
}

unsigned int NTForm::GetRelativeY( void ) {
	return 0;
}

void NTForm::SetCenterPositionFormOnSize( unsigned int width , unsigned int height ) {
	NTScreen *scr = NTGetGlobalScreen();
	SetSize( width , height );
	SetPos( (scr->GetWidth()-uWidth) / 2, (scr->GetHeight()-uHeight) / 2 );
}

}
