/*
 * Copyright 2018-2024, ttcoder of TTS LLC
 * Distributed under the terms of the MIT license.
 */
#ifndef CanvasGenode_H
#define CanvasGenode_H



// genode/base.lib.a
#include <os/pixel_rgb888.h>
#include <os/surface.h>

// genode/base.lib.a extras..
#include <gui_session/connection.h>

// haiku.lib.so
#include <interface/InterfaceDefs.h>  // rgb_color
#include <interface/Rect.h>
#include <support/String.h>  // member (in case HAS_MICRO_WINDOW_MANAGER is defined below)
class BBitmap;
class BGradient;
class BGradientLinear;
class BPolygon;


// Client-side decorations, Client-side window management:
// Ideally we would have Genode-style server side decorations and window management,
// but can't get the WM to work and not sure how to implement Be-style non rectangular
// decorations, so go with client-side for now, as this is high-return-for-moderate-investment:


// UPD: this is now defined in the *Jamfile*, so that we may override it (when building for SculptOS eg)
//#define HAS_MICRO_WINDOW_MANAGER  // aka "HAS_ClientSide_Decorations_and_WinManager"



///ToDo: rename to "GenodeWindow" ?  or "SurfacePainterGe" (since it can paint to a NP window or to a BBitmap's buffer)
class CanvasGenode
{
	/*
	Wrapper around genode framebuffers, which acts like a BView (server side or not)
	*/
	
	// AKA
	// - CanvasForNitpickerWindowFramebuffer
	// - PicassoAppServerLikeCanvas_ClientSideInsteadOfServerSideThough ^-^
	
	//using namespace Genode;
	typedef Genode::Surface_base::Point Point;
	typedef Genode::Surface_base::Area  Area;
	typedef Genode::Surface_base::Rect  Rect;
	///
	typedef Genode::Pixel_rgb888 PT;  // used to be: rgb565 (up until Genode 20.05)
	///
	
public:

		CanvasGenode(
			Genode::Env & genode_env,
			Gui::Connection & server_events,
			BBitmap * use_offscreen_painting
			);
		~CanvasGenode();
		
		void Rebuffer_Inner( const Gui::Rect inner_rect );
#if defined( HAS_MICRO_WINDOW_MANAGER )
		// decorations, CS (Client-Side)
		void SetInsets_DecorCS( BRect tab_frame, float border_thickness );
		void SetTitle_DecorCS( const char * title );
		
		Gui::Rect DecoratedOuterRect_For_Inner( const Rect inner_rect ) const;
			// used in here, and by NitpickerInternals::reGeom()
#endif
		
		// dealing with BViews and screen-framebuffer
		void SetOriginAndClipping( BPoint origin, BRect clipping );
		void Update();
		
		// primitives drawing to 'surface' (either fb, or bitmap)
		void StrokeLine( BPoint p1, BPoint p2, rgb_color color );
		void StrokeTriangle( BPoint p1, BPoint p2, BPoint p3, rgb_color color );
		void FillTriangle( BPoint p1, BPoint p2, BPoint p3, rgb_color color );
		void StrokePolygon( const BPolygon & polygon, const BPoint priv_points[], rgb_color col );
		void FillPolygon( const BPolygon & polygon, const BPoint priv_points[], rgb_color col );
		void FillPolygon( const BPolygon & polygon, const BPoint priv_points[], const BGradient & gradient );
		void StrokeRect( BRect rect, rgb_color color );
		void StrokeRoundRect( BRect rect, float xrad, float yrad, rgb_color color );
		void FillRect( BRect rect, rgb_color color );
		void FillRect( BRect rect, const BGradient & gradient );
		void FillRoundRect( BRect rect, float xrad, float yrad, rgb_color color );
		void StrokeEllipse( BRect rect, rgb_color color );
		void StrokeArc( BRect rect, float start_angle, float arc_angle, rgb_color color );
		void FillEllipse( BRect rect, rgb_color color );
		void FillArc(
			BRect rect,
			float start_angle,
			float arc_angle,
			rgb_color color
			);
		void DrawString( const char * string, int length, BPoint where, rgb_color color );
		void DrawBitmap(
			const BBitmap * bitmap,
			const BRect bm_chopping,
			const BPoint where );
		void FillRainbow();// int scr_w, int scr_h );
		
		// gradients
		void FillRect( BRect rect, const BGradientLinear & gradient );


private:  // Code

		void rebufferOuter( const Gui::Area outer_area );
#if defined( HAS_MICRO_WINDOW_MANAGER )
		void updateDecor();
#endif
		
		void doBoundedArc(
			int x0,
			int x1,
			int y0,
			int y1,
			bool fill,
			rgb_color color,
			int width,
			int height,
			BPoint origin_local
			);
		
		void doArc_allQuadrants(
			bool fill,
			BRect rect_local,
			float start_angle,
			float arc_angle,
			rgb_color color
			);
		void doArc_Quadrant(
			int quadrant,
			bool fill,
			rgb_color color,
			const int width,
			const int height,
			BPoint origin_local,
			float start_angle,
			float end_angle
			);
		
		void setPixel_LocalCoords( int x_local, int y_local, rgb_color color );
		void Bitmap_painter(
				const BPoint where,//Genode::Surface_base::Point position,
				Genode::Surface<PT> & surface,
				const BBitmap & bitmap,
				const BRect source_rect
				);


private:  // Data

		// Base
		
		Genode::Env &
			env;
		
		// NP & Canvas
		//
		
		// on-screen back-end:
		Gui::Connection
			& nitServer;//serverEvents;
		Genode::Attached_dataspace
			* screenCanvas;  // framebuffer dataspace, handled by Nitpicker
		
		// off-screen back-end:
		BBitmap * memoryCanvas;  // off-screen pixel buffer
		
#if defined( HAS_MICRO_WINDOW_MANAGER )
		// Client-Side Decor (if we're doing it client-side instead of server-side):
		BString csdTitle;  // BWindow.Title()
		BRect csdTab;  // yellow tab's frame
		float csdBorder;  // border thickness
#endif
		
		Genode::Surface_base::Area
			_size;  // the *actual* framebuffer size (*overall*, optionally including extra surface covered by client-side decorations)
		
		// no 'BRect innerRect', we extrapolate it on-the-fly in SetOriginAndClipping(), from the outer_rect/_size and from csdBorder/Tab
		
		// Context, from SetViewPort():
		//
		
		BPoint	currentOrigin;  // includes both decorator-offset and BView-origin-offset
		BRect	clipRect;  // in window coordinates (raw framebuffer, thus needs to include all offsets)


private:  // FORBIDDEN

		CanvasGenode( const CanvasGenode & );
		CanvasGenode & operator=( const CanvasGenode & );
};



#endif // CanvasGenode_H

