/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "Be.h"


// constructor
BWindow::BWindow (BRect frame, const char *title, window_type type, uint32 flags, uint32 workspace) :
BLooper (title),
fFrame (frame),
fFlags (flags),
fDefaultButton (0)
{
#ifdef _DEBUG
	winBe::debugMessage ("BWindow constructor");
#endif // _DEBUG

	fLook = static_cast<window_look>(type);
	fFeel = static_cast<window_feel>(type);
	SetTitle (title);
}


BWindow::BWindow (BMessage* archive)
{
}


// destructor
BWindow::~BWindow ()
{
#ifdef _DEBUG
	winBe::debugMessage ("BWindow destructor: " + std::string (Title ()));
#endif // _DEBUG

	// Delete views
	for (std::list<BView*>::iterator i = viewList.begin (); i != viewList.end (); ++i) {
		delete *i;
		winBe::destroyView (*i);
	}
}


// Quit
void BWindow::Quit ()
{
#ifdef _DEBUG
	winBe::debugMessage ("BWindow quit");
#endif // _DEBUG

	if (!fTerminating) {
		fTerminating = true;
		winBe::destroyWindow (this);
		winBe::postQuitMessage (Thread ()); // terminate thread
		delete this;
	}
}


void BWindow::DispatchMessage (BMessage *message, BHandler *handler)
{
	MessageReceived (message);
}


void BWindow::MessageReceived (BMessage *message)
{
	Lock ();

	BView* view = 0;
	BScrollBar* scrollBar = 0;

	switch (message->what) {

		case B_MINIMIZE:
			Minimize (message->FindBool ("minimize"));
			break;

		case B_KEY_DOWN:
			view->KeyDown (message->FindString ("byte"), message->FindInt32 ("num_bytes"));
			break;

		case B_KEY_UP:
			view->KeyUp (message->FindString ("byte"), message->FindInt32 ("num_bytes"));
			break;

		case B_MOUSE_DOWN:
			view->MouseDown (message->FindPoint ("where"));
			break;

		case B_MOUSE_UP:
			view->MouseUp (message->FindPoint ("where"));
			break;

		case B_MOUSE_MOVED:
		{
			BMessage* aMessage = 0;
			message->FindMessage ("a_message", aMessage);
			view->MouseMoved (message->FindPoint ("where"), message->FindInt32 ("code"), aMessage);
			break;
		}

		case B_VIEW_MOVED:
			view->FrameMoved (message->FindPoint ("new_position"));
			break;

		case B_VIEW_RESIZED:
			view->FrameResized (message->FindFloat ("new_width"), message->FindFloat ("new_height"));
			break;

		case B_VALUE_CHANGED:
			scrollBar->ValueChanged (message->FindFloat ("new_value"));
			break;

		case B_WINDOW_ACTIVATED:
			WindowActivated (message->FindBool ("state"));
			break;

		case B_WINDOW_MOVED:
			FrameMoved (message->FindPoint ("new_position"));
			break;

		case B_WINDOW_RESIZED:
			FrameResized (message->FindFloat ("new_width"), message->FindFloat ("new_height"));
			break;

		case B_SCREEN_CHANGED:
			ScreenChanged (message->FindRect ("screen_size"), static_cast<color_space>(message->FindInt32 ("depth")));
			break;

		case B_WORKSPACE_ACTIVATED:
			WorkspaceActivated (message->FindInt32 ("ws"), message->FindBool ("state"));
			break;

		case B_WORKSPACES_CHANGED:
			WorkspacesChanged (message->FindInt32 ("old_ws"), message->FindInt32 ("new_ws"));
			break;

		case B_PULSE:
			view->Pulse ();
			break;

		case B_QUIT_REQUESTED:
			if (!fTerminating)
				if (QuitRequested ())
					Quit ();
			break;

		case B_ZOOM:
			Zoom ();
			break;

		default:
			BLooper::MessageReceived (message);
			break;

	}

	delete message;
	Unlock ();
}


void BWindow::FrameMoved (BPoint new_position)
{
}


void BWindow::WorkspacesChanged (uint32 old_ws, uint32 new_ws)
{
}


void BWindow::WorkspaceActivated (int32 ws, bool state)
{
}


void BWindow::FrameResized (float new_width, float new_height)
{
}


void BWindow::Minimize (bool minimize)
{
}


void BWindow::Zoom ()
{
}


void BWindow::Zoom (BPoint rec_position, float rec_width, float rec_height)
{
}


void BWindow::ScreenChanged (BRect screen_size, color_space depth)
{
}


void BWindow::MenusBeginning ()
{
}


void BWindow::MenusEnded ()
{
}


void BWindow::WindowActivated (bool state)
{
}


void BWindow::Show ()
{
	resume_thread (fTaskID);
}


void BWindow::Hide ()
{
}


BHandler* BWindow::ResolveSpecifier (BMessage *msg, int32 index, BMessage *specifier, int32 form, const char *property)
{
	return 0;
}


status_t BWindow::GetSupportedSuites (BMessage *data)
{
	return 0;
}


status_t BWindow::Perform (perform_code d, void *arg)
{
	return 0;
}


// QuitRequested
bool BWindow::QuitRequested ()
{
	return true;
}


// Run
thread_id BWindow::Run ()
{
#ifdef _DEBUG
	winBe::debugMessage ("BWindow::Run");
#endif // _DEBUG

	// Create the window
	winBe::createWindow (this, fTitle, fFrame.left, fFrame.top, fFrame.right, fFrame.bottom);

	//snooze (100000); // cause other threads to run

	// Create the views
	for (std::list<BView*>::iterator i = viewList.begin (); i != viewList.end (); ++i) {
		BRect frame = (*i)->Frame ();
		(*i)->set_owner (this);
		winBe::createView (*i, this, (*i)->Name (), frame.left, frame.top, frame.right, frame.bottom);
		winBe::setViewColor (*i, (*i)->color.red, (*i)->color.green, (*i)->color.blue);
		(*i)->createChildren ();
	}

	return BLooper::Run ();
}


void BWindow::task_looper ()
{
}


BMessage* BWindow::ConvertToMessage (void *raw, int32 code)
{
	return 0;
}


status_t BWindow::Archive (BMessage *data, bool deep) const
{
	return 0;
}


// SetTitle
void BWindow::SetTitle (const char *title)
{
	fTitle = title;
}


// Frame
BRect BWindow::Frame () const
{
	return fFrame;
}


void BWindow::_ReservedWindow1 ()
{
}


void BWindow::_ReservedWindow2 ()
{
}


void BWindow::_ReservedWindow3 ()
{
}


void BWindow::_ReservedWindow4 ()
{
}


void BWindow::_ReservedWindow5 ()
{
}


void BWindow::_ReservedWindow6 ()
{
}


void BWindow::_ReservedWindow7 ()
{
}


void BWindow::_ReservedWindow8 ()
{
}


// AddChild
void BWindow::AddChild (BView *child, BView *before)
{
	if (!before)
		viewList.push_back (child);
	else {
		for (std::list<BView*>::iterator i = viewList.begin (); i != viewList.end (); ++i) {
			if (*i == before) {
				viewList.insert (i, child);
				break;
			}
		}
	}

	child->set_owner (this);
	child->AttachedToWindow ();
	child->AllAttached ();
}


// Bounds
BRect BWindow::Bounds () const
{
	BRect rect (fFrame);
	rect.OffsetBy (-rect.left, -rect.top);

	int width, height;
	winBe::getWindowFurnitureSize (const_cast<BWindow*>(this), width, height);

	rect.right -= width;
	rect.bottom -= height;

	return rect;
}


// callWindowQuitRequested
bool winBe::callWindowQuitRequested (BWindow* window)
{
	BWindow* bWindow = static_cast<BWindow*>(window);
	return bWindow->QuitRequested ();
}


void BWindow::SetDefaultButton(BButton *button)
{
	fDefaultButton = button;
}


BButton* BWindow::DefaultButton() const
{
	return fDefaultButton;
}


void BWindow::MoveTo(BPoint p)
{
	MoveTo (p.x, p.y);
}


void BWindow::MoveTo (float x, float y)
{
}


void BWindow::ResizeTo (float width, float height)
{
	fFrame.right = fFrame.left + width;
	fFrame.bottom = fFrame.top + height;
	winBe::setWindowSize (this, fFrame.Width (), fFrame.Height ());
}


void BWindow::ResizeBy (float width, float height)
{
	fFrame.right += width;
	fFrame.bottom += height;
	winBe::setWindowSize (this, fFrame.Width (), fFrame.Height ());
}


void BWindow::UpdateIfNeeded ()
{
	winBe::updateWindow (this);
}

BView* BWindow::FindView (const char* view_name) const
{
	return 0;
}

const char* BWindow::Title () const
{
	return fTitle.c_str ();
}
