#include "config.h"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/rexxsyslib.h>


char *amiga2unix(const char *a)
{
	static char str[512];

	int i = 0;
//	fprintf(stderr, "aus '%s' wird ", a);
	while(*a == '/'  &&  i < 509)
	{
		str[i++] = '.';
		str[i++] = '.';
		str[i++] = '/';
		a++;
	}
	strncpy(str + i, a, 511 - i);
	str[511] = 0;
//	fprintf(stderr, "path: '%s'.\n", str);
	return str;
}


void catPath(char *path, const char *file)
{
	char c, tmp[256], *dst;
	int v = 1;

	dst = tmp;
	while((c = *file++)  &&  (dst-tmp < 255))
	{
		if(c == '.'  &&  v)
		{
			if(*file == '/'  ||  (*file == '.'  &&  *(file+1) == '/'))
			{
				file ++;
				c = *file++;
				if(!c)  break;
			}
		}
		else if(c == '/')
		{
			v = 1;
		}
		else
		{
			v = 0;
		}
		*dst++ = c;
	}
	*dst = 0;
	AddPart(path, tmp, 1024);
}


char *getpwd_amiga(void)
{
	static char *pwd;
	if(!pwd)
	{
		BPTR lock = Lock("", SHARED_LOCK);
		if(lock)
		{
			pwd = (char*) xmalloc(512);
			NameFromLock(lock, pwd, 512);
			UnLock(lock);
		}
	}
	return pwd;
}


char *fileAsSymbol(const char *file)
{
	static char s [256];
	int i;

	strncpy(s, (const char*)FilePart((STRPTR)file), 256);
	s[255] = 0;

	for (i=strlen(s)-1; i>=0; i--)
	{
		if (!isalpha(s[i]))
		{
			s[i] = '_';
		}
	}
	return s;
}


void removeQuotationMarks(char *str)
{
    if(*str == '\"')
    {
        char c;
        int i, o = 1;
        for(i=0; ; i++)
        {
            c = str[i + o];
            if(c == 0)
            {
                str[i] = 0;
                break;
            }
            else if(c == '\"')
            {
                o++;
                i--;
            }
            else
            {
                str[i] = c;
            }
        }
    }
}


static void escapeARexxStringInPlace(char *s)
{
	char c;
	int i, nq = 0;

	for(i=0; c=s[i]; i++)
	{
		if(c == '\"')
			nq ++;
	}

	while(nq > 0  &&  i >= 0)
	{
		c = s[i];
		if(c == '\"')
		{
			s[i + nq] = c;
			nq --;
		}
		s[i + nq] = c;
		i --;
	}
}


struct RxsLib *RexxSysBase = NULL;
static struct MsgPort *replyPort;
static char stringbuffer[4096];

char *errportname = NULL;
const char *errportfile = NULL;
const char *errportsource = NULL;
int errportline = -1;
int errportkind = ERRKIND_MESSAGE;
char errportmessage[4096];


static void stormexit(void)
{
    if(RexxSysBase)
    {
        CloseLibrary((struct Library*) RexxSysBase);
        RexxSysBase = NULL;
    }
	if(replyPort)
	{
		DeleteMsgPort(replyPort);
		replyPort = NULL;
	}
}


int storminit(void)
{
	atexit(stormexit);
	errportmessage[0] = 0;

    RexxSysBase = (struct RxsLib*) OpenLibrary("rexxsyslib.library", 36);
    if(!RexxSysBase)
    {
        fprintf(stderr, "Failed to open rexxsyslib.library V36.\n");
        return 0;
    }

    replyPort = CreateMsgPort();
    if(!replyPort)
    {
        fprintf(stderr, "Failed to create ARexx-replyport.\n");
        return 0;
    }

    return 1;
}


void stormvsendf(const char *portname, const char *format, va_list args)
{
	if(replyPort  &&  portname)
	{
		struct RexxMsg *msg = CreateRexxMsg(replyPort, NULL, NULL);
		vsprintf(stringbuffer, format, args);
		//escapeARexxStringInPlace(stringbuffer);

		if(msg)
		{
			if(msg->rm_Args[0] = CreateArgstring(stringbuffer, strlen(stringbuffer)))
			{
				struct MsgPort *sendPort;

				Forbid();
				if(sendPort = FindPort((STRPTR)portname))
				{
					PutMsg(sendPort, (struct Message*)msg);
					Permit();

					WaitPort(replyPort);
					while(GetMsg(replyPort));
				}
				else
				{
					Permit();
				}
				DeleteArgstring(msg->rm_Args[0]);
			}
			DeleteRexxMsg(msg);
		}
	}
}


void stormsendf(const char *portname, const char *format, ...)
{
	va_list args;
	va_start(args, format);
	stormvsendf(portname, format, args);
	va_end(args);
}



void stormMessage(char *errstr)
{
    if (errportname  &&  replyPort)
    {
        struct RexxMsg *msg;
        int mode;
        char *s;

        switch (errportkind)
        {
            case ERRKIND_MESSAGE:
                mode = 22;
                break;

            case ERRKIND_WARNING:
                mode = 21;
                break;

            case ERRKIND_ERROR:
                mode = 20;
                break;

            case ERRKIND_FATAL:
                mode = 19;
                break;

            default:
                mode = 22;
        }

        sprintf(stringbuffer, "ERROR 0 MODE %d STRINGS \"", mode);
		s = stringbuffer + strlen(stringbuffer);
		strcpy(s, errstr);
		escapeARexxStringInPlace(s);
        strcat(stringbuffer, "\"");

        if (errportfile)      sprintf(stringbuffer + strlen(stringbuffer), " FILE \"%s\"", errportfile);
        if (errportline >= 0) sprintf(stringbuffer + strlen(stringbuffer), " LINE %d", errportline);
        if (errportsource)    sprintf(stringbuffer + strlen(stringbuffer), " SOURCE \"%s\"", errportsource);

        errportfile = NULL;
        errportsource = NULL;
        errportline = -1;
        errportkind = ERRKIND_MESSAGE;

        msg = CreateRexxMsg(replyPort, NULL, NULL);
        if(msg)
        {
            if(msg->rm_Args[0] = CreateArgstring(stringbuffer, strlen(stringbuffer)))
            {
                struct MsgPort *sendPort;

                Forbid();
                if(sendPort = FindPort(errportname))
                {
                    PutMsg(sendPort, (struct Message*)msg);
                    Permit();

                    WaitPort(replyPort);
                    while(GetMsg(replyPort));
                }
                else
                {
                    Permit();
                }
                DeleteArgstring(msg->rm_Args[0]);
            }
            DeleteRexxMsg(msg);
        }
    }
}


void stormvsendfKFL(int kind, const char *file, int line, const char *format, va_list args)
{
    if (errportname  &&  replyPort)
    {
        struct RexxMsg *msg;
        char *s;
        int mode;

        switch (kind)
        {
            case ERRKIND_MESSAGE:
                mode = 22;
                break;

            case ERRKIND_WARNING:
                mode = 21;
                break;

            case ERRKIND_ERROR:
                mode = 20;
                break;

            case ERRKIND_FATAL:
                mode = 19;
                break;

            default:
                mode = 22;
        }

        sprintf(stringbuffer, "ERROR 0 MODE %d STRINGS \"", mode);
        s = stringbuffer + strlen(stringbuffer);
        vsprintf(s, format, args);
        escapeARexxStringInPlace(s);
        strcat(stringbuffer, "\"");

        if(file)
        {
			sprintf(stringbuffer + strlen(stringbuffer), " FILE \"%s\"", file);
			if(line)
			{
				sprintf(stringbuffer + strlen(stringbuffer), " LINE %d", line);
			}
		}

        msg = CreateRexxMsg(replyPort, NULL, NULL);
        if(msg)
        {
            if(msg->rm_Args[0] = CreateArgstring(stringbuffer, strlen(stringbuffer)))
            {
                struct MsgPort *sendPort;

                Forbid();
                if(sendPort = FindPort(errportname))
                {
                    PutMsg(sendPort, (struct Message*)msg);
                    Permit();

                    WaitPort(replyPort);
                    while(GetMsg(replyPort));
                }
                else
                {
                    Permit();
                }
                DeleteArgstring(msg->rm_Args[0]);
            }
            DeleteRexxMsg(msg);
        }
    }
}


void stormsendfKFL(int kind, const char *file, int line, const char *format, ...)
{
	va_list args;
	va_start(args, format);
	stormvsendfKFL(kind, file, line, format, args);
	va_end(args);
}
