#include <stdio.h>
#include <unistd.h>
#include <directfb.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <string>

#define DFBCHECK(x...)                                         \
  {                                                            \
    DFBResult err = x;                                         \
                                                               \
    if (err != DFB_OK)                                         \
      {                                                        \
        fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \
        DirectFBErrorFatal( #x, err );                         \
      }                                                        \
  }

// Font path
#define FONT_FN "/opt/roku/fonts/DejaVuLGCSans.ttf"

int main(int argc, char **argv)
{
	IDirectFB *dfb = NULL;
	IDirectFBSurface *primary = NULL;
	
	// Initialize DFB
	DFBCHECK (DirectFBInit (&argc, &argv));
	DFBCHECK (DirectFBCreate (&dfb));
	DFBCHECK (dfb->SetCooperativeLevel (dfb, DFSCL_EXCLUSIVE));

	// Create Primary surface
	DFBSurfaceDescription dsc;
	dsc.flags = DSDESC_CAPS;
	dsc.caps  = static_cast<DFBSurfaceCapabilities>(DSCAPS_PRIMARY | DSCAPS_FLIPPING);
	DFBCHECK(dfb->CreateSurface( dfb, &dsc, &primary ));

	// Fill to 20x20 of surface with transparent black
	DFBCHECK(primary->SetColor(primary, 0x0, 0x0, 0x0, 0x0));
	DFBCHECK(primary->FillRectangle(primary, 0, 0, 20, 20));

	// Create font width 20
	DFBFontDescription desc;
	desc.flags = static_cast<DFBFontDescriptionFlags>(DFDESC_WIDTH);
	desc.width = 20;
	desc.height = 20;
	IDirectFBFont * font;
	dfb->CreateFont(dfb, FONT_FN, &desc, &font);
	DFBCHECK(primary->SetFont(primary, font));

	// Draw white "O" character
	DFBCHECK(primary->SetColor(primary, 255,255,255,255));
	DFBCHECK(primary->SetDrawingFlags(primary, DSDRAW_DST_PREMULTIPLY ));
	DFBCHECK(primary->DrawString(primary, "O", 1, 0, 0, (DFBSurfaceTextFlags)(DSTF_TOP | DSTF_LEFT)));
	DFBCHECK(primary->Flip(primary, NULL, static_cast<DFBSurfaceFlipFlags>(DSFLIP_ONSYNC)));

	// Dump the contents of the resultant framebuffer, first color, then alpha
	// We should see an "O" in the alpha, but the color should be empty
	int pitch;
	unsigned char *framebuffer;
	DFBCHECK(primary->Lock(primary, DSLF_READ, (void **)&framebuffer, &pitch));

	printf("Color\n");
	for(int y = 0; y < 20; ++y)
	{
		unsigned char *p = &framebuffer[y * pitch];
		for(int x = 0; x < 20; ++x)
		{
			printf("%02x", p[0]);
			p += 4;
		}
		printf("\n");
	}

	printf("\n");
	printf("\n");
	printf("Alpha\n");
	for(int y = 0; y < 20; ++y)
	{
		unsigned char *p = &framebuffer[y * pitch];
		for(int x = 0; x < 20; ++x)
		{
			printf("%02x", p[3]);
			p += 4;
		}
		printf("\n");
	}

	DFBCHECK(primary->Unlock(primary));
	
	font->Release(font);
	primary->Release(primary);
	dfb->Release(dfb);
	
	return 0;
}
