#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/cybergraphics_protos.h>
#include <clib/graphics_protos.h>
#include <pragmas/cybergraphics_pragmas.h>
#include <cybergraphx/cybergraphics.h>
#include <stdio.h>
#include <iostream.h>
 
#include "renderer.h"
#include "misc/omegamsg.h"
#include "output/output.h"

Renderer::Renderer(){
	win=NULL;
	scr=NULL;
	oa_SetName("Renderer");
	bgBuffer=NULL;
}

Renderer::~Renderer(){
	delete bgBuffer;
}


BOOL Renderer::StartUp(){
	BOOL result=FALSE;
	
	coordPort=FindPort("ProjectOmega");		// Find the port we need to signal
	if (!coordPort){
		Error("Unable To Find ProjectOmega","I Need the Main Program!");
	}
	else{
		LoadBackGround();
		if(OmegaApp::Initialise(NULL)){
			dataMessage->om_Type=OMEGARENDERER;
			dataMessage->om_Class=OM_INIT;
			SendToPort(coordPort,TRUE);
			result=TRUE;
		}
	}
	return result;
}

void Renderer::OpenScr(ULONG scrMode){

#pragma chip
	static UWORD pointer[1]={0};
#pragma fast

	ULONG OpenErr;
	cout << "Screen Mode " << scrMode << endl;
			
	scr=OpenScreenTags(NULL,
  		SA_DisplayID,  scrMode,
  	   SA_ErrorCode,  &OpenErr,
  	   SA_ShowTitle,  FALSE,
  	   SA_Draggable,  FALSE,
  	   TAG_DONE); 
  	   	
	if (scr){
		if(GetBitMapAttr(scr->sc_RastPort.rp_BitMap,BMA_DEPTH)<=8){
			CloseScreen(scr);
			Error("Bad Screen Depth","Please Select >8 bit Screen Mode");
			scr=NULL;
		}
		else{
			win=OpenWindowTags(NULL,		// Open a backdrop window to hide the titlebar
				WA_Width, 	scr->Width,
				WA_Height, 	scr->Height,
				WA_Left, 	0,
				WA_Top, 		0,
				WA_Flags, 	WFLG_BORDERLESS | WFLG_BACKDROP,
				WA_CustomScreen, scr,
				TAG_DONE);
			SetPointer(win,pointer,0,0,0,0);
			if (bgBuffer)
				ScalePixelArray((APTR)bgBuffer,bgW,bgH,bgW*3,&(scr->sc_RastPort),0,0,
									scr->Width,scr->Height,RECTFMT_RGB);
		}
	}
	else
		Error("Unable to Open Screen.","Invalid Screen Mode?");
}

void Renderer::CloseScr(){
	if (win){
		CloseWindow(win);
		win=NULL;
	}
	if (scr){
		CloseScreen(scr);
		scr=NULL;
	}
}

void Renderer::BlitOutput(BitMap *bm, Rectangle *rect){
	// Blit the output to the current bitmap
	BltBitMap(bm,rect->MinX,rect->MinY,
				ob_bmMain,				
				rect->MinX,rect->MinY,
				rect->MaxX-rect->MinX,
				rect->MaxY-rect->MinY,
				0xC0,0xFF,0);
}				
				
void Renderer::WaitForSignals(){
	UINT signals;

	signals=Wait(OUTPUTSIGNAL | SIGBREAKF_CTRL_C);

	if (signals & OUTPUTSIGNAL)
		DealWithMessages();
	if (signals & SIGBREAKF_CTRL_C){
		OnStop();
		oa_SetStatus(APP_STATUS_QUIT,TRUE);
	}
}

void Renderer::DealWithMessages(){
	OmegaMessage *msg;
	Rectangle *blitRect;
	BitMap *bm;
	
	while(msg=(OmegaMessage *)GetMsg(basePort)){
		switch(msg->om_Class){
		case OM_QUIT:
			CloseScr();
			OnQuit();
			ReplyMsg((Message *)msg);
			break;
		case OM_INIT:
			OnStart();
			OpenScr((ULONG)(msg->om_Scr));							// Open our window
			if (scr)
				ob_bmMain=scr->sc_RastPort.rp_BitMap;
			msg->om_Scr=scr;
			ReplyMsg((Message *)msg);
			break;
		case OM_STOP:
			OnStop();
			CloseScr();
			ReplyMsg((Message *)msg);
			break;
		case OM_RENDER:
			blitRect=(Rectangle *)msg->om_Misc;
			bm=((RastPort *)(msg->om_Scr))->rp_BitMap;
			if (scr){
				BlitOutput(bm,blitRect);
			}
		}
	}
}

void Renderer::LoadBackGround(){
	FILE *file=fopen("omegabg.pbm","r");
	
	ULONG bufSize, w,h;
	ULONG result;
		
	if (bgBuffer)
		delete[] bgBuffer;		// Delete anything we may have here!
			
	// PPM files are in format P6\nWidth\nHeight\n255\n
	if (file){
		result=fscanf(file,"P6\n%ld\n%ld\n255\n", &w, &h);
		if (result==2){
			bufSize=w*h*3;
			bgW=w;bgH=h;
			bgBuffer=new UBYTE[bufSize];
			// read the file into the buffer
			fread(bgBuffer,bufSize,1,file);
			fclose(file);
		}
		else
			cout << "Not a valid ppm file" << endl;
		fclose(file);
	}
	else
		cout << "Unable to open background file" << endl;
}
