/*
 * This file is part of the FEddi package
 *
 * Personal use allowed under the terms of the
 *
 *              GNU GENERAL PUBLIC LICENSE Version 2
 *              (see LICENSE for the complete text)
 *
 *-------------------------------------------------------------------
 *
 *    ENTER AT YOUR OWN RISK !!
 *
 * This source is without any documentation and can drive you mad.
 * In case of sudden epileptic seizures please call your doctor.
 *
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include "regex.h"
#include "regex_priv.h"
#include <ncurses.h>
#include "structs.h"
#include "proc.h"
#include "template.h"
#include "colors.h"
#include "inout.h"

extern LineListType *MsgTxt, *Kludges;
extern int MsgLines, KludgeLines;

char **ShellCommand=NULL;
int maxSC=0;

const char IFMODE[6][6]=
{
	"from",
	"to",
	"subj",
	"mode",
	"area",
	"group"
};

void loadtxt(int);
void quotetext(LineListType **text, int *lines, MsgHdrType hdr, int q);
char *TransQuote(char *s);

void TextTemplate(char *oarea, char *area, char *group, char *mode, MsgHdrType old,
		MsgHdrType new, int *x, int *y)
{
	char file[PATH_MAX], *d1, *d2, line[512], dummy[100], value[100];
	FILE *tmpl=NULL, **otmpl=NULL;
	LineListType *ntxt=NULL;
	int nlines=0, j, copy, ifcount=0, ifval[100], i, offs, error=0, notmpl=0;
	struct re_pattern_buffer regex;
	struct re_registers regs;
	for (i=0; i<maxSC; i++) free(ShellCommand[i]);
	free(ShellCommand);
	ShellCommand=NULL;
	maxSC=0;
	sprintf(file,"%s+%s/template",BasePath,area);
	if ((tmpl=fopen(file,"rt"))==NULL)
	{	
		sprintf(file,"%stemplate",BasePath);
		if ((tmpl=fopen(file,"rt"))==NULL)
		{
			if (MsgTxt)
			{
				for (j=0; j<MsgLines; j++) free(MsgTxt[j].line);
				free(MsgTxt);
				MsgTxt=NULL;
			}
			MsgLines=0;
			return;
		}
	}
	loop:
	while (fgets(file,300,tmpl))
	{
		if ((d1=strrchr(file,'\n'))) *d1=0;
		for (i=strlen(file)-1; file[i]==32; file[i]=0, i--);
		if (strncmp(file,"#;",2)==0) continue;
		if (error) goto err;
		if (strncmp(file,"#include ",9)==0)
		{
			notmpl++;
			otmpl=(FILE **)realloc(otmpl,sizeof(FILE *)*notmpl);
			otmpl[notmpl-1]=tmpl;
			if ((d1=strchr(file,32)))
			{
				d1++;
				extendhome(d1);
				if ((tmpl=fopen(d1,"rt")))
					continue;
			}
			tmpl=otmpl[notmpl-1];
			notmpl--;
			continue;
		}
		if (strncmp(file,"#if ",4)==0)
		{
			for (i=0; i<6; i++)
				if (strncasecmp(file+4,IFMODE[i],strlen(IFMODE[i]))==0) break;
			if (i==6)
			{
				strcat(file,"!expression error");
				error=1;
				goto err;
			}
			offs=4;
			switch (i)
			{
				case 0:
					sprintf(value,"%s (%u:%u/%u.%u)",new.WhoFrom,
							new.OrigZone,new.OrigNet,new.OrigNode,new.OrigPoint);
					break;
				case 1:
					sprintf(value,"%s (%u:%u/%u.%u)",new.WhoTo,
							new.DestZone,new.DestNet,new.DestNode,new.DestPoint);
					offs=2;
					break;
				case 2:
					strcpy(value,new.Subj); 
					break;
				case 3:
					strcpy(value,mode);
					break;
				case 4:
					strcpy(value,area);
					break;
				case 5:
					strcpy(value,group);
					offs=5;
					break;
			}
			for (d1=file+4+offs; *d1==32; d1++);
			memset(&regex,0,sizeof(struct re_pattern_buffer));
			regex.translate=RE_ICASE_TRANS_MAP;
			re_set_syntax(RE_SYNTAX_POSIX_EGREP);
			if (re_compile_pattern(d1,strlen(d1),&regex))
			{
				strcat(file,"!can't compile regex");
				error=1;
				goto err;
			}
			ifcount++;
			if (ifcount>100)
			{
				strcat(file,"!too many if's");
				error=1;
				goto err;
			}
			ifval[ifcount-1]=
				(re_search(&regex,value,strlen(value),0,strlen(value),&regs)>=0);
			continue;
		}
		if (strncmp(file,"#else",5)==0)
		{
			ifval[ifcount-1]=1-ifval[ifcount-1];
			continue;
		}
		if (strncmp(file,"#endif",6)==0)
		{
			ifcount--;
			if (ifcount<0)
			{
				strcat(file,"!too many endif's");
				error=1;
				goto err;
			}
			continue;
		}
		err:
		for (i=0, copy=1; i<ifcount; i++) copy=(copy&&ifval[i]);
		if (copy || error)
		{
			if (strcmp(file,"#text")==0)
			{
				quotetext(&ntxt,&nlines,old,0);
				continue;
			}
			if (strcmp(file,"#quote")==0)
			{
				quotetext(&ntxt,&nlines,old,1);
				continue;
			}
			if (strcmp(file,"#cross")==0)
			{
				nlines++;
				ntxt=(LineListType *)realloc(ntxt,LineListSize*nlines);
				ntxt[nlines-1].Quote=ntxt[nlines-1].CutOrigin=0;
				ntxt[nlines-1].CR=1;
				ntxt[nlines-1].line=(char *)malloc(40);
				strcpy(ntxt[nlines-1].line,"$%&PUT-CROSSPOST-INFO-HERE&%$");
				continue;
			}
			if (strncmp(file,"#|",2)==0)
			{
				maxSC++;
				ShellCommand=(char **)realloc(ShellCommand,sizeof(char *)*maxSC);
				ShellCommand[maxSC-1]=(char *)malloc(strlen(file+2)+1);
				strcpy(ShellCommand[maxSC-1],file+2);
				continue;
			}
			line[0]=0;
			for (d1=file; (d2=strchr(d1,'#'))!=NULL; d1=d2)
			{
				*d2++=0;
				strcat(line,d1);
				switch (*d2++)
				{
					case '@': /* Address */
						switch (*d2++)
						{
							case 'f':
								sprintf(dummy,"%u:%u/%u%c%u",
										old.OrigZone,old.OrigNet,old.OrigNode,
										old.OrigPoint?'.':0,old.OrigPoint);
								strcat(line,dummy);
								break;
							case 'F':
								sprintf(dummy,"%u:%u/%u%c%u",
										new.OrigZone,new.OrigNet,new.OrigNode,
										new.OrigPoint?'.':0,new.OrigPoint);
								strcat(line,dummy);
								break;
							case 'e':
								if (strcmp(mode,"cc")==0)
									strcat(line,"#@e");
								else
								{
									sprintf(dummy,"%u:%u/%u%c%u",
											old.DestZone,old.DestNet,old.DestNode,
											old.DestPoint?'.':0,old.DestPoint);
									strcat(line,dummy);
								}
								break;
							case 'E':
								if (strcmp(mode,"cc")==0)
									strcat(line,"#@E");
								else
								{
									sprintf(dummy,"%u:%u/%u%c%u",
											new.DestZone,new.DestNet,new.DestNode,
											new.DestPoint?'.':0,new.DestPoint);
									strcat(line,dummy);
								}
								break;
						}
						break;
					case 'd': /* Orig Date */
						strncat(line,old.DateTime,9);
						break;
					case 'D': /* Act Date */
						DateTime(dummy);
						strncat(line,dummy,9);
						break;
					case 't': /* Orig Time */
						d1=strrchr(old.DateTime,32)+1;
						strcat(line,d1);
						break;
					case 'T': /* Act Time */
						DateTime(dummy);
						d1=strrchr(dummy,32)+1;
						strcat(line,d1);
						break;
					case '1': /* firstname */
						switch (*d2++)
						{
							case 'f': /* Orig From */
								strcpy(dummy,old.WhoFrom);
								d1=strchr(dummy,32);
								if (d1) *d1=0;
								strcat(line,dummy);
								break;
							case 'F': /* Act From */
								strcpy(dummy,new.WhoFrom);
								d1=strchr(dummy,32);
								if (d1) *d1=0;
								strcat(line,dummy);
								break;
							case 'e': /* Orig Dest */
								if (strcmp(mode,"cc")==0)
									strcat(line,"#1e");
								else
								{
									strcpy(dummy,old.WhoTo);
									d1=strchr(dummy,32);
									if (d1) *d1=0;
									strcat(line,dummy);
								}
								break;
							case 'E': /* Act Dest */
								if (strcmp(mode,"cc")==0)
									strcat(line,"#1E");
								else
								{
									strcpy(dummy,new.WhoTo);
									d1=strchr(dummy,32);
									if (d1) *d1=0;
									strcat(line,dummy);
								}
								break;
						}
						break;
					case '2': /* lastname */
						switch (*d2++)
						{
							case 'f': /* Orig From */
								strcpy(dummy,old.WhoFrom);
								d1=strrchr(dummy,32);
								if (d1)
									d1++;
								else
									d1=dummy;
								strcat(line,d1);
								break;
							case 'F': /* Act From */
								strcpy(dummy,new.WhoFrom);
								d1=strrchr(dummy,32);
								if (d1)
									d1++;
								else
									d1=dummy;
								strcat(line,d1);
								break;
							case 'e': /* Orig Dest */
								if (strcmp(mode,"cc")==0)
									strcat(line,"#2e");
								else
								{
									strcpy(dummy,old.WhoTo);
									d1=strrchr(dummy,32);
									if (d1)
										d1++;
									else
										d1=dummy;
									strcat(line,d1);
								}
								break;
							case 'E': /* Act Dest */
								if (strcmp(mode,"cc")==0)
									strcat(line,"#2E");
								else
								{
									strcpy(dummy,new.WhoTo);
									d1=strrchr(dummy,32);
									if (d1)
										d1++;
									else
										d1=dummy;
									strcat(line,d1);
								}
								break;
						}
						break;
					case 'f': /* Orig From */
						strcat(line,old.WhoFrom);
						break;
					case 'F': /* Act From */
						strcat(line,new.WhoFrom);
						break;
					case 'e': /* Orig Dest */
						if (strcmp(mode,"cc")==0)
							strcat(line,"#e");
						else
							strcat(line,old.WhoTo);
						break;
					case 'E': /* Act Dest */
						if (strcmp(mode,"cc")==0)
							strcat(line,"#E");
						else
							strcat(line,new.WhoTo);
						break;
					case 's': /* Orig Subj */
						strcat(line,old.Subj);
						break;
					case 'S': /* Act Subj */
						strcat(line,new.Subj);
						break;
					case 'a': /* Orig Area */
						strcat(line,oarea);
						break;
					case 'A': /* Act Area */
						strcat(line,area);
						break;
					case '.': /* Cursor starting pos */
						*x=strlen(line);
						*y=nlines;
						break;
					case '#':
						strcat(line,"#");
						break;
				}
			}
			strcat(line,d1);
			nlines++;
			ntxt=(LineListType *)realloc(ntxt,LineListSize*nlines);
			ntxt[nlines-1].Quote=ntxt[nlines-1].CutOrigin=0;
			ntxt[nlines-1].CR=1;
			ntxt[nlines-1].line=(char *)malloc(strlen(line)+1);
			strcpy(ntxt[nlines-1].line,line);
		}
	}
	if (notmpl)
	{
		fclose(tmpl);
		tmpl=otmpl[notmpl-1];
		notmpl--;
		goto loop;
	}
	free(otmpl);
	fclose(tmpl);
	if (MsgTxt)
	{
		for (j=0; j<MsgLines; j++) free(MsgTxt[j].line);
		free(MsgTxt);
		MsgTxt=NULL;
	}
	MsgTxt=ntxt;
	MsgLines=nlines;
}

void quotetext(LineListType **text, int *lines, MsgHdrType hdr, int q)
{
	int i, w, pos;
	char quote[20], *d1, *newquote;
	if (q)
	{
		quote[0]=32;
		for (i=0, d1=hdr.WhoFrom; d1 && i<17; d1=strchr(d1,32))
			if (d1)
			{
				if (i) d1++;
				if (tolower(*d1)>='a' && tolower(*d1)<='z')
					quote[1+i++]=*d1;
			}
		quote[1+i++]='>';
		quote[1+i++]=32;
		quote[1+i]=0;
		w=strlen(quote);
	} else
		w=0;
	loadtxt(QuoteLength-w);
	for (i=0; i<MsgLines; i++)
	{
		if (!q && strncmp(MsgTxt[i].line,"---",3)==0)
			if (MsgTxt[i].line[3]==0 || MsgTxt[i].line[3]==32)
				break;
		(*lines)++;
		(*text)=(LineListType *)realloc((*text),*lines*LineListSize);
		if (q)
		{
			(*text)[*lines-1].CR=1;
			(*text)[*lines-1].Quote=MsgTxt[i].line[0]!=0;
		} else
		{
			(*text)[*lines-1].CR=MsgTxt[i].CR;
			(*text)[*lines-1].Quote=MsgTxt[i].Quote;
		}
		if (MsgTxt[i].line[0])
		{
			(*text)[*lines-1].line=(char *)malloc(strlen(MsgTxt[i].line)+w+1);
			if (q)
			{
				if ((pos=GetQuotePos(MsgTxt[i].line)))
				{
					pos--;
					if ((newquote=TransQuote(MsgTxt[i].line)))
					{
						strcpy((*text)[*lines-1].line,newquote);
						strcat((*text)[*lines-1].line,(MsgTxt[i].line[pos]==32)?
							&(MsgTxt[i].line[pos+1]):&(MsgTxt[i].line[pos]));
						free(newquote);
						newquote=NULL;
					}
				} else
				{
					strcpy((*text)[*lines-1].line,quote);
					strcat((*text)[*lines-1].line,MsgTxt[i].line);
					if (strcmp(MsgTxt[i].line,"---")==0 ||
							strncmp(MsgTxt[i].line,"--- ",4)==0 ||
							strncmp(MsgTxt[i].line," * Origin:",10)==0)
						(*text)[*lines-1].line[w+1]='!';
				}
				(*text)[*lines-1].Quote=IsQuote((*text)[*lines-1].line);
				(*text)[*lines-1].CutOrigin=0;
			} else
			{
				strcpy((*text)[*lines-1].line,MsgTxt[i].line);
				if (strcmp(MsgTxt[i].line,"---")==0 ||
						strncmp(MsgTxt[i].line,"--- ",4)==0 ||
						strncmp(MsgTxt[i].line," * Origin:",10)==0)
					(*text)[*lines-1].line[1]='!';
				(*text)[*lines-1].Quote=IsQuote((*text)[*lines-1].line);
				(*text)[*lines-1].CutOrigin=MsgTxt[i].CutOrigin;
			}
		} else
		{
			(*text)[*lines-1].line=(char *)malloc(1);
			(*text)[*lines-1].line[0]=0;
			(*text)[*lines-1].CutOrigin=0;
		}
	}
}

void ExeShellCommand(char *area)
{
	FILE *rp, *wp;
	char narea[80], **args, *d1;
	int i, pid, save;
	if (maxSC)
	{
		args=(char **)malloc(2*sizeof(char *));
		args[1]=NULL;
		for (i=0; i<maxSC; i++)
		{
			if ((d1=strrchr(ShellCommand[i],'/')))
				d1++;
			else
				d1=ShellCommand[i];
			args[0]=strdup(d1);
			if ((pid=pipecall(ShellCommand[i],args,&rp,&wp))>0)
			{
				pipeMsg(pid,rp,wp,65535,COLS,&save,narea,NULL,
						&MsgLines,&MsgTxt,&KludgeLines,&Kludges,NULL,NULL);
			}
			free(args[0]);
		}
	}
	for (i=0; i<maxSC; i++) free(ShellCommand[i]);
	free(ShellCommand);
	ShellCommand=NULL;
	maxSC=0;
}

void EndTemplate()
{
	int i;
	for (i=0; i<maxSC; i++) free(ShellCommand[i]);
	free(ShellCommand);
	ShellCommand=NULL;
	maxSC=0;
}

void AfterTextTemplate(MsgHdrType hdr)
{
	char line[PATH_MAX], dummy[PATH_MAX], *d1, *d2;
	int i;
	for (i=0; i<MsgLines; i++)
	{
		line[0]=0;
		for (d1=MsgTxt[i].line; (d2=strchr(d1,'#'))!=NULL; d1=d2)
		{
			*d2++=0;
			strcat(line,d1);
			switch (*d2++)
			{
				case '@': /* Address */
					switch (*d2++)
					{
						case 'e':
							sprintf(dummy,"%u:%u/%u%c%u",
									hdr.DestZone,hdr.DestNet,hdr.DestNode,
									hdr.DestPoint?'.':0,hdr.DestPoint);
							strcat(line,dummy);
							break;
						case 'E':
							sprintf(dummy,"%u:%u/%u%c%u",
									hdr.DestZone,hdr.DestNet,hdr.DestNode,
									hdr.DestPoint?'.':0,hdr.DestPoint);
							strcat(line,dummy);
							break;
					}
					break;
				case '1': /* firstname */
					switch (*d2++)
					{
						case 'e': /* Orig Dest */
							strcpy(dummy,hdr.WhoTo);
							d1=strchr(dummy,32);
							if (d1) *d1=0;
							strcat(line,dummy);
							break;
						case 'E': /* Act Dest */
							strcpy(dummy,hdr.WhoTo);
							d1=strchr(dummy,32);
							if (d1) *d1=0;
							strcat(line,dummy);
							break;
					}
					break;
				case '2': /* lastname */
					switch (*d2++)
					{
						case 'e': /* Orig Dest */
							strcpy(dummy,hdr.WhoTo);
							d1=strrchr(dummy,32);
							if (d1)
								d1++;
							else
								d1=dummy;
							strcat(line,d1);
							break;
						case 'E': /* Act Dest */
							strcpy(dummy,hdr.WhoTo);
							d1=strrchr(dummy,32);
							if (d1)
								d1++;
							else
								d1=dummy;
							strcat(line,d1);
							break;
					}
					break;
				case 'e': /* Orig Dest */
					strcat(line,hdr.WhoTo);
					break;
				case 'E': /* Act Dest */
					strcat(line,hdr.WhoTo);
					break;
			}
		}
		strcat(line,d1);
		free(MsgTxt[i].line);
		MsgTxt[i].line=(char *)malloc(strlen(line)+1);
		strcpy(MsgTxt[i].line,line);
	}
}
