#ifdef __XCODE__
#include "xcode_quiet.h"
#endif

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#define DMID 8
#include "debug.h"
#include "mpair.h"
#include "lib.h"

#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
/*
Like pair, but use qmalloc


typedef struct MPAIR {
	char *var;
	char *val;
	struct MPAIR *next;
} MPair;

typedef struct {
	MPair *first;
	Qmalloc *qmalloc;
} MPairList;

*/

#ifndef iseol
#	define iseol(x) (x == '\r' || x == '\n' || x == '\0')
#endif

MPairList *mpair_new(void)
{

	MPairList *mp = calloc(1,sizeof(MPairList));
	mp->qmalloc = qmalloc_new(1000); // I"m really tempted to put the structure into itself..., nope bad idea as then we can't compress it. 
	return mp;
}

char *mpair_find(MPairList *qp, char *name)
{
	MPair *p;
	if (qp==NULL) return "";
	for (p=qp->first;p!=NULL;p=p->next) {
		if (strcmp(p->var,name)==0) return p->val;
	}
	return "";
}
char *mpair_findnc(MPairList *qp, char *name)
{
	MPair *p;
	if (qp==NULL) return "";
	for (p=qp->first;p!=NULL;p=p->next) {
		if (strcmpnc(p->var,name)==0) return p->val;
	}
	return "";
}
int mpair_add(MPairList **pqp, char *var, char *val) // and avoids duplicates.
{
	MPair *p;
	MPairList *qp = *pqp;
	if (qp==NULL) qp = *pqp = mpair_new();
	for (p=qp->first;p!=NULL;p=p->next) {
		if (strcmp(p->var,var)==0) {
			p->val = qstrdup(qp->qmalloc,val);
			return TRUE;
		}
	}
	p = qcalloc(qp->qmalloc,sizeof(MPair));
	
	p->var = qstrdup(qp->qmalloc,var);
	p->val = qstrdup(qp->qmalloc,val);
	p->next = qp->first;
	qp->first = p;
	return TRUE;
}
void mpair_copy(MPairList **dst, MPairList *src)
{
	MPair *s;
	if (*dst!=NULL) lib_abort();
	*dst = mpair_new();
	if (src==NULL) return; // NOTHING TO COPY ACROSS
	for(s=src->first; s!=NULL;  s = s->next) {
		mpair_add(dst,s->var,s->val);
	}

}
void mpair_reverse(MPairList **src) 
{
	MPairList *newlist=NULL;
	mpair_copy(&newlist,*src);
	mpair_free(src);
	*src = newlist;
}
void mpair_remove(MPairList *qp, char *var, char *val) 
{
	// Yes this leaks memory, but shouldn't matter.
	MPair *p;
	MPair **last;
	if (qp==NULL) return; // nothing to delete.
	last = &qp->first;
	for (p=qp->first;p!=NULL;p=p->next) {
		if (strcmp(p->var,var)==0) {
			if (val==NULL || strcmp(val,p->val)==0) {
				*last = p->next;
			}
		} else {
			last = &p->next;
		}		
	}
}
void mpair_removenc(MPairList *qp, char *var, char *val) 
{
	// Yes this leaks memory, but shouldn't matter.
	MPair *p;
	MPair **last;
	if (qp==NULL) return; // nothing to delete.
	last = &qp->first;
	for (p=qp->first;p!=NULL;p=p->next) {
		if (strcmpnc(p->var,var)==0) {
			if (val==NULL || strcmpnc(val,p->val)==0) {
				*last = p->next;
			}
		} else {
			last = &p->next;
		}		
	}
}


int mpair_add_atend(MPairList **pqp, char *var, char *val)
{
	MPairList *qp = *pqp;
	MPair *p;
	MPair *m,*last=NULL;
	if (qp==NULL) qp = *pqp = mpair_new();
	p = qcalloc(qp->qmalloc,sizeof(MPair));
	p->var = qstrdup(qp->qmalloc,var);
	p->val = qstrdup(qp->qmalloc,val);

	for (m=qp->first;m!=NULL;m=m->next) {
		last = m;
	}
	if (last!=NULL) {
		last->next = p;
	} else qp->first = p;
	return TRUE;
}

int mpair_free(MPairList **qp)
{
	if (*qp==NULL) return TRUE; // nothing to do.
	qmalloc_free_all((*qp)->qmalloc);
	free(*qp);
	*qp = NULL;
	return TRUE;
}
MPair *mpair_first(MPairList *m)
{
	if (m==NULL) return NULL;
	return m->first;
}
int mpair_test(void)
{
	MPairList *mp = mpair_new();
	MPair *m;
	int i;
	qmalloc_test();
	for (i=0;i<100; i++) {
		mpair_add_atend(&mp,"a111","b111");
	}
	mpair_add(&mp,"var1","val1");
	mpair_add(&mp,"var2","val2");
	mpair_add(&mp,"var3","val3");
	mpair_add(&mp,"var4","val4");
	mpair_remove(mp,"var3",NULL);
	mpair_remove(mp,"var2","val2");
	mpair_add(&mp,"var1","val5again");
	mpair_add_atend(&mp,"last","val5again");
	printf("Find var1 %s\n",mpair_find(mp,"var1"));
	printf("Find var2 %s\n",mpair_find(mp,"var2"));
	printf("Find var4 %s\n",mpair_find(mp,"var4"));
	for (m=mp->first;m!=NULL;m=m->next) {
		printf("showall %s=%s\n",m->var,m->val);
	}
	mpair_reverse(&mp);
	for (m=mp->first;m!=NULL;m=m->next) {
		printf("showallrev %s=%s\n",m->var,m->val);
	}

	mpair_free(&mp);
	return TRUE;
}