//========================================================================
//
// Apdfppc.cc
//
// Copyright 1999 Emmanuel Lesueur
//
//========================================================================

//#define DEBUGMSG

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <exec/nodes.h>
#include <exec/memory.h>
#include <powerup/ppcproto/exec.h>
#include <powerup/ppclib/message.h>
#include <powerup/ppclib/tasks.h>
#include <powerup/gcclib/powerup_protos.h>
#include "AComm.h"
#include "AGfxcomm.h"

int init(int,const char*);
void quit();
int get_info(int* num_pages);
int get_page_size(int page,int* width,int* height);
int create_doc(BPTR,const char* filename,size_t,size_t);
int create_output_dev(int depth,struct ColorMap* colormap);
void delete_output_dev(void);
int simple_find(const char* str,int top,int* xmin,int* ymin,int* xmax,int* ymax);
int init_find(const char*);
int find(int start,int stop,int* xmin,int* ymin,int* xmax,int* ymax,int* page);
void end_find();
int chklink(int x,int y,void** action,char* str,size_t len);
int dolink(int* x,int* y,int* state,int* page,char* buf,size_t len);
int init_write(const char* filename,int first_page,int last_page,int zoom,int rotate,int type);
void writefile(int first_page,int last_page);
void end_write();
char* gettext(int,int,int,int);
int show_page(int,int);
void add_fontmap(const char*,const char*,int,int,int);
/*void rem_fontmap(const char*);*/
void clear_fontmap();
/*void set_fontmap();*/
int init_scan();
int scan_fonts(int,int);
int scan_default_fonts();
void end_scan_fonts();
int get_font(int,char*,int,char*,int,int*,int*,int*);

bool quitting=false;

void* port68k;
void* portppc;
void* reply_port;
void* syncmsg;
void* ports_list;

void cleanup() {
    if(syncmsg)
	PPCDeleteMessage(syncmsg);

    if(ports_list)
	PPCDeletePortList(ports_list);

    if(reply_port)
	PPCDeletePort(reply_port);
}

int main() {

    StartupData* sd=(StartupData*)PPCGetTaskAttr(PPCTASKTAG_STARTUP_MSGDATA);
    port68k=sd->port;
    portppc=(void*)PPCGetTaskAttr(PPCTASKTAG_MSGPORT);

    atexit(&cleanup);

    if(sd->id!=VMAGIC) {
	printf("The PPC module does not match the 68k executable.\n");
	exit(EXIT_FAILURE);
    }
    if(!init(sd->colors,sd->gzipcmd))
	exit(EXIT_FAILURE);

    reply_port=PPCCreatePort(NULL);

    void* ports[3];
    ports[0]=portppc;
    ports[1]=reply_port;
    ports[2]=NULL;
    ports_list=PPCCreatePortList(ports,0);

    if(reply_port && ports_list)
	syncmsg=PPCCreateMessage(reply_port,0);

    if(reply_port && syncmsg && ports_list) {

	PPCSendMessage(port68k,syncmsg,(APTR)VMAGIC,0,MSGID_SYNC);
	PPCWaitPort(reply_port);
	PPCGetMessage(reply_port);

	bool running=true;
	while(running) {

	    PPCWaitPortList(ports_list);

	    while(void* msg=PPCGetMessage(reply_port))
		PPCDeleteMessage(msg);

	    while(void* msg=PPCGetMessage(portppc)) {
		ULONG id=PPCGetMessageAttr(msg,PPCMSGTAG_MSGID);
		switch(id) {
		  case MSGID_QUIT:
		    //quit();
		    running=false;
		    break;
		  case MSGID_CREATEDOC: {
		    msg_createdoc* m=(msg_createdoc*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
		    m->base.success=create_doc(m->dir,m->filename,m->cachesz,m->blocsz);
		    break;
		  }
#if 0
		  case MSGID_DELETEDOC:
		    delete_doc();
		    break;
#endif
		  case MSGID_INFO: {
		    msg_info* m=(msg_info*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
		    m->base.success=get_info(&m->num_pages);
		    break;
		  }
		  case MSGID_PAGESIZE: {
		    msg_pagesize* m=(msg_pagesize*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
		    m->base.success=get_page_size(m->page,&m->width,&m->height);
		    break;
		  }
		  case MSGID_CREATEOUTPUTDEV: {
		    msg_create_output_dev* m=(msg_create_output_dev*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
		    m->base.success=create_output_dev(m->depth,m->colormap);
		    break;
		  }
		  case MSGID_DELETEOUTPUTDEV:
		    delete_output_dev();
		    break;

		  case MSGID_PAGE: {
		    msg_page* m=(msg_page*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
		    m->base.success=show_page(m->page_num,m->zoom);
		    break;
		  }
		  case MSGID_CHKLINK: {
		    msg_chklink* m=(msg_chklink*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
		    m->base.success=chklink(m->x,m->y,&m->action,m->str,sizeof(m->str));
		    break;
		  }
		  case MSGID_DOLINK: {
		    msg_dolink* m=(msg_dolink*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
		    m->base.success=dolink(&m->x,&m->y,&m->state,&m->page,m->str,sizeof(m->str));
		    break;
		  }
		  case MSGID_SIMPLEFIND: {
		    msg_find* m=(msg_find*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
		    m->base.success=simple_find(m->str,m->top,&m->xmin,&m->ymin,&m->xmax,&m->ymax);
		    break;
		  }
		  case MSGID_INITFIND: {
		    msg_find* m=(msg_find*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
		    m->base.success=init_find(m->str);
		    break;
		  }
		  case MSGID_FIND: {
		    msg_find* m=(msg_find*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
		    m->base.success=find(m->top,m->bottom,&m->xmin,&m->ymin,&m->xmax,&m->ymax,&m->page);
		    break;
		  }
		  case MSGID_ENDFIND:
		    end_find();
		    break;
		  case MSGID_INITWRITE: {
		    msg_write* m=(msg_write*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
		    m->base.success=init_write(m->filename,m->first_page,m->last_page,m->zoom,m->rotate,m->type);
		    break;
		  }
		  case MSGID_WRITE: {
		    msg_write* m=(msg_write*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
		    writefile(m->first_page,m->last_page);
		    break;
		  }
		  case MSGID_ENDWRITE:
		    end_write();
		    break;
		  case MSGID_GETTEXT: {
		    msg_gettext* m=(msg_gettext*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
		    char* p=gettext(m->xmin,m->ymin,m->xmax,m->ymax);
		    if(m->base.success=p!=NULL) {
			m->size=strlen(p);
			PPCReplyMessage(msg);
			PPCWaitPort(portppc);
			msg=PPCGetMessage(portppc);
			size_t sz=PPCGetMessageAttr(msg,PPCMSGTAG_DATALENGTH);
			char* q=(char*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
			strncpy(q,p,sz-1);
			q[sz-1]='\0';
			free(p);
		    }
		    break;
		  }
		  case MSGID_ADDFONTMAP: {
		    msg_fontmap* m=(msg_fontmap*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
		    add_fontmap(m->pdffont,m->afont,m->m,m->style,m->encoding);
		    break;
		  }
		  /*case MSGID_REMFONTMAP: {
		    msg_fontmap* m=(msg_fontmap*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
		    rem_fontmap(m->pdffont);
		    break;
		  }*/
		  case MSGID_CLEARFONTMAP:
		    clear_fontmap();
		    break;

		  /*case MSGID_SETFONTMAP:
		    set_fontmap();
		    break;*/

		  case MSGID_INITSCAN: {
		    msg_scan_fonts* m=(msg_scan_fonts*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
		    m->base.success=init_scan();
		    break;
		  }
		  case MSGID_SCANFONTS: {
		    msg_scan_fonts* m=(msg_scan_fonts*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
		    m->base.success=scan_fonts(m->first_page,m->last_page);
		    break;
		  }

		  case MSGID_DEFAULTFONTS: {
		    msg_scan_fonts* m=(msg_scan_fonts*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
		    m->base.success=scan_default_fonts();
		    break;
		  }

		  case MSGID_ENDSCANFONTS:
		    end_scan_fonts();
		    break;

		  case MSGID_GETFONT: {
		    msg_fontmap* m=(msg_fontmap*)PPCGetMessageAttr(msg,PPCMSGTAG_DATA);
		    m->base.success=get_font(m->m,m->pdffont,sizeof(m->pdffont),m->afont,sizeof(m->afont),&m->m,&m->style,&m->encoding);
		    break;
		  }

		}
		PPCReplyMessage(msg);
	    }
	}
    }

}

