/*
 * Copyright 2003-2009, Haiku Inc.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		Stefano Ceccherini (burton666@libero.it)
 *		Axel Dörfler, axeld@pinc-software.de
 */


#include <Screen.h>

#include <Window.h>

#ifndef HoG_GENODE
#include <PrivateScreen.h>


using namespace BPrivate;

#else  // HoG:
	///later: move the Genode-specific code to a _GeScreen.cpp file
#	include <gui_session/connection.h>
#	include <app/Application.h>  // be_app
#endif  // ~HoG


BScreen::BScreen(screen_id id)
{
#ifndef HoG_GENODE
	fScreen = BPrivateScreen::Get(id.id);
#endif
}


BScreen::BScreen(BWindow* window)
{
#ifndef HoG_GENODE
	fScreen = BPrivateScreen::Get(window);
#endif
}


BScreen::~BScreen()
{
#ifndef HoG_GENODE
	BPrivateScreen::Put(fScreen);
#endif
}


bool
BScreen::IsValid()
{
#ifndef HoG_GENODE
	return fScreen != NULL && fScreen->IsValid();
#else
	return true;
#endif
}


#ifndef HoG_GENODE
status_t
BScreen::SetToNext()
{
	if (fScreen != NULL) {
		BPrivateScreen* screen = BPrivateScreen::GetNext(fScreen);
		if (screen != NULL) {
			fScreen = screen;
			return B_OK;
		}
	}
	return B_ERROR;
}
#endif


color_space
BScreen::ColorSpace()
{
#ifndef HoG_GENODE
	if (fScreen != NULL)
		return fScreen->ColorSpace();

	return B_NO_COLOR_SPACE;
#else  // HoG_GENODE
	return B_NO_COLOR_SPACE;
///later-2: implement via be_app.VideoMode (but already seems ok with BColorControl, i.e. we want to make sure to not return *B_CMAP8*, otherwise BColorControl goes to "palette mode")
#endif  //~HoG_GENODE
}


BRect
BScreen::Frame()
{
#if defined( HoG_GENODE )
	// Required by Deskbar, BAlert, BMenu.calcFrame()...
	
	// Note to BScreen users: if your app is run early in the boot process (like
	// e.g. Deskbar), make sure to listen to ScreenChanged() hook calls!
	// In upstream Be this is not as critical, because the very first call to BScreen.Frame()
	// is generally correct, only subject to user-initiated screen resolution changes,
	// whereas with Nitpicker we get "0x0" resolution until the video driver is launched and
	// attaches itself to nitpicker, informing Nitpicker of the actual 1280x768 etc resolution.
	
	///later: OPTIM ? E.g. this is used in TBarView::MouseMoved() (!), so maybe cache the rect in a 'static' during a few ms (not initially, only after getting a non 0x0 value) -- low priority though : tracing shows that this only slows down the "move across roster entries" case (bottom of deskbar), but does not slow down the "browse top menu" case
	
	// transient NP connection
	Gui::Connection nitpicker( be_app->Env() );
	// adapt as per ticket #5353:
	auto const area = nitpicker.panorama().convert<Gui::Area>(
		[&] (Gui::Rect rect) { return rect.area; },
		[&] (Gui::Undefined) { return Gui::Area { 0, 0 }; }
		);
	BSize size(
			area.w,
			area.h
		);
	if( size.width < 640 ) size.width  = 640;
	if( size.height< 480 ) size.height = 480;
	
	return BRect(
		0.,
		0.,
		size.width -1.,  // e.g. 1024 -1
		size.height -1.  // e.g.  768 -1
		);

#else  // upstream:

	if (fScreen != NULL)
		return fScreen->Frame();

	return BRect(0, 0, 0, 0);
#endif  // ~upstream
}


#ifndef HoG_GENODE

screen_id
BScreen::ID()
{
	if (fScreen != NULL) {
		screen_id id = { fScreen->ID() };
		return id;
	}

	return B_MAIN_SCREEN_ID;
}


status_t
BScreen::WaitForRetrace()
{
	return WaitForRetrace(B_INFINITE_TIMEOUT);
}


status_t
BScreen::WaitForRetrace(bigtime_t timeout)
{
	if (fScreen != NULL)
		return fScreen->WaitForRetrace(timeout);

	return B_ERROR;
}
#endif  //~HoG_GENODE


uint8
BScreen::IndexForColor(uint8 red, uint8 green, uint8 blue, uint8 alpha)
{
#ifndef HoG_GENODE
	if (fScreen != NULL)
		return fScreen->IndexForColor(red, green, blue, alpha);

	return 0;
#else  // HoG_GENODE
	return 0;
///later: review? (but should be okay for BColorControl..?)
#endif  // ~HoG_GENODE
}


rgb_color
BScreen::ColorForIndex(const uint8 index)
{
#ifndef HoG_GENODE
	if (fScreen != NULL)
		return fScreen->ColorForIndex(index);

	return rgb_color();
#else  // HoG_GENODE
	return rgb_color();
#endif  // ~HoG_GENODE
}


#ifndef HoG_GENODE
uint8
BScreen::InvertIndex(uint8 index)
{
	if (fScreen != NULL)
		return fScreen->InvertIndex(index);

	return 0;
}

#endif


const color_map*
BScreen::ColorMap()
{
#ifndef HoG_GENODE
	if (fScreen != NULL)
		return fScreen->ColorMap();

	return NULL;
#else
	// in HoG we reverse the relationship, we go client-side (libbe.so's system_colors())
	// instead of going server-side (app_server):
	return system_colors();
#endif
}


#ifndef HoG_GENODE

#if defined( HoG_GENODE )
///ToDo: see http://genodians.org/jschlatow/2021-06-10-screenshot-component
// though that package does "too much", the whole shebang from bitmap to writing a png file,
// whereas we probably just needs the following:
// - open a Capture session (for Get/ReadBitmap() to work)
// - config/nitpicker += KEY_PRINT  (for our "input server")
#endif  // ~HoG_GENODE

status_t
BScreen::GetBitmap(BBitmap** _bitmap, bool drawCursor, BRect* bounds)
{
	if (fScreen != NULL)
		return fScreen->GetBitmap(_bitmap, drawCursor, bounds);

	return B_ERROR;
}


status_t
BScreen::ReadBitmap(BBitmap* bitmap, bool drawCursor, BRect* bounds)
{
	if (fScreen != NULL)
		return fScreen->ReadBitmap(bitmap, drawCursor, bounds);

	return B_ERROR;
}
#endif  // ~HoG_GENODE


rgb_color
BScreen::DesktopColor()
{
#ifndef HoG_GENODE
	///later-Set/Desktopcolor
	if (fScreen != NULL)
		return fScreen->DesktopColor(B_CURRENT_WORKSPACE_INDEX);
#else
	return make_color( 60, 100, 160 );  // for now: a shade of blue slightly lighter than Haiku's
#endif  // ~HoG_GENODE

	return rgb_color();
}


rgb_color
BScreen::DesktopColor(uint32 workspace)
{
#ifndef HoG_GENODE
	if (fScreen != NULL)
		return fScreen->DesktopColor(workspace);
#endif  // ~HoG_GENODE

	return rgb_color();
}


void
BScreen::SetDesktopColor(rgb_color color, bool stick)
{
#ifndef HoG_GENODE
	if (fScreen != NULL)
		fScreen->SetDesktopColor(color, B_CURRENT_WORKSPACE_INDEX, stick);
#endif  // ~HoG_GENODE
}



void
BScreen::SetDesktopColor(rgb_color color, uint32 workspace, bool stick)
{
#ifndef HoG_GENODE
	if (fScreen != NULL)
		fScreen->SetDesktopColor(color, workspace, stick);
#else
	///later todo: setdesktopcolor
#endif
}


#ifndef HoG_GENODE
#if 0

status_t
BScreen::ProposeMode(display_mode* target, const display_mode* low,
	const display_mode* high)
{
	if (fScreen != NULL)
		return fScreen->ProposeMode(target, low, high);

	return B_ERROR;
}


status_t
BScreen::GetModeList(display_mode** _modeList, uint32* _count)
{
	if (fScreen != NULL)
		return fScreen->GetModeList(_modeList, _count);

	return B_ERROR;
}


status_t
BScreen::GetMode(display_mode* mode)
{
	if (fScreen != NULL)
		return fScreen->GetMode(B_CURRENT_WORKSPACE_INDEX, mode);

	return B_ERROR;
}


status_t
BScreen::GetMode(uint32 workspace, display_mode* mode)
{
	if (fScreen != NULL)
		return fScreen->GetMode(workspace, mode);

	return B_ERROR;
}


status_t
BScreen::SetMode(display_mode* mode, bool makeDefault)
{
	if (fScreen != NULL)
		return fScreen->SetMode(B_CURRENT_WORKSPACE_INDEX, mode, makeDefault);

	return B_ERROR;
}


status_t
BScreen::SetMode(uint32 workspace, display_mode* mode, bool makeDefault)
{
	if (fScreen != NULL)
		return fScreen->SetMode(workspace, mode, makeDefault);

	return B_ERROR;
}


status_t
BScreen::GetDeviceInfo(accelerant_device_info* info)
{
	if (fScreen != NULL)
		return fScreen->GetDeviceInfo(info);

	return B_ERROR;
}


status_t
BScreen::GetMonitorInfo(monitor_info* info)
{
	if (fScreen != NULL)
		return fScreen->GetMonitorInfo(info);

	return B_ERROR;
}


status_t
BScreen::GetPixelClockLimits(display_mode* mode, uint32* _low, uint32* _high)
{
	if (fScreen != NULL)
		return fScreen->GetPixelClockLimits(mode, _low, _high);

	return B_ERROR;
}


status_t
BScreen::GetTimingConstraints(display_timing_constraints* constraints)
{
	if (fScreen != NULL)
		return fScreen->GetTimingConstraints(constraints);

	return B_ERROR;
}


status_t
BScreen::SetDPMS(uint32 dpmsState)
{
	if (fScreen != NULL)
		return fScreen->SetDPMS(dpmsState);

	return B_ERROR;
}


uint32
BScreen::DPMSState()
{
	if (fScreen != NULL)
		return fScreen->DPMSState();

	return 0;
}


uint32
BScreen::DPMSCapabilites()
{
	if (fScreen != NULL)
		return fScreen->DPMSCapabilites();

	return 0;
}


status_t
BScreen::GetBrightness(float* brightness)
{
	if (fScreen != NULL)
		return fScreen->GetBrightness(brightness);
	return B_ERROR;
}


status_t
BScreen::SetBrightness(float brightness)
{
	if (fScreen != NULL)
		return fScreen->SetBrightness(brightness);
	return B_ERROR;
}


//	#pragma mark - Deprecated methods


BPrivate::BPrivateScreen*
BScreen::private_screen()
{
	return fScreen;
}


status_t
BScreen::ProposeDisplayMode(display_mode* target, const display_mode* low,
	const display_mode* high)
{
	return ProposeMode(target, low, high);
}


void*
BScreen::BaseAddress()
{
	if (fScreen != NULL)
		return fScreen->BaseAddress();

	return NULL;
}


uint32
BScreen::BytesPerRow()
{
	if (fScreen != NULL)
		return fScreen->BytesPerRow();

	return 0;
}

#endif
#endif

