#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include "debug.h"
#include "lib.h"
#include "lprintf.h"
#include "profile.h"


Profile *profile_copy(Profile *p);
static Profile *list;
int profile_append(Profile *p)
{
	p->next = list;
	list = p;
	return TRUE;
}
int profile_reverse(void)
{
	Profile *p,*next;
	Profile *start=list;

	list = NULL;
	for (p=start;p!=NULL;p=next) {
		next = p->next;

		p->next = list;
		list = p;
	}
	return TRUE;
}
Profile *profile_find_id(int id)
{
	// Find the last matching profile
	Profile *p;
	for (p=list;p!=NULL;p=p->next) {
		if (p->id==id) return profile_copy(p);
	}
	return NULL;
}

Profile *profile_find_id_add(int id)
{
	// Find the last matching profile
	Profile *p,*newp;
	p = profile_find_id(id);
	if (p!=NULL) return p;
	newp = calloc(1,sizeof(Profile));
	newp->id = id;

	for (p=list;p!=NULL;p=p->next) {
		if (p->next==NULL) {
			p->next = newp;
			break;
		}
	}
	return profile_copy(newp);
}

int profile_getnp(Profile *pro, char *setting, int i, char *p[], char *bf)
{
	int np;
	lprintf(bf,BFSZ-1,"%s%d",setting,i);
	ncpy(bf,profile_get(pro,bf),BFSZ-1);
	np = token_split(bf,p,"|",10);
	return np;
}
char *profile_getp(Profile *pro, char *setting, int i, char *tmp)
{
	int np;
	char *p[100];
	char bf[BFSZ];
	ncpy(bf,profile_get(pro,setting),BFSZ-1);
	np = token_split(bf,p,"|",10);
	if (np<=i) return "";
	ncpy(tmp,p[i],BFSZ-1);
	return tmp;
}

char *profile_get(Profile *p, char *setting)
{
	if (p==NULL) return "";
	if (p->pairs==NULL) return "";
	return pair_find(p->pairs,setting);
}
int profile_init(char *fname, char *reason)
{
	FILE *f;
	char *s;
	char p1[BFSZ];
	char bf[BFSZ];
	char *upto;
	static int id;
	Profile *pro=NULL;
	f = fopen(fname,"r");
	if (f==NULL) {
		lprintf(reason,BFSZ-1,"Unable to open (%s) %s err=%d",fname,strerror(errno),errno);
		return FALSE;
	}
	for (;!feof(f);) {
		if (fgets(bf,BFSZ-1,f)==NULL) break;
		s = mystrtok(bf,"|\r\n",&upto);
		if (s==NULL) continue;
		ncpy(p1,s,BFSZ-1);
		s = mystrtok(NULL,"\r\n",&upto);
		if (s==NULL) continue;
		if (strcmp(p1,"profile")==0) {
			// Add current one to linked list and start new one...
			if (pro!=NULL) {
				profile_append(pro); pro = NULL;
			}
			pro = calloc(1,sizeof(Profile));
			pro->id = ++id;
			pair_add(&pro->pairs,p1,s);
		} else {
			if (pro!=NULL) 	pair_add(&pro->pairs,p1,s);
		}
	}
	fclose(f);
	if (pro!=NULL) profile_append(pro); pro=NULL;
	profile_reverse();
	if (list==NULL) {
		strcpy(reason,"No profiles found, cannot continue");
		return FALSE; 
	}
	return TRUE;
}
int profile_set_var(Profile *p, char *var, char *val)
{
	return pair_add(&p->pairs,var,val);
}
Profile *profile_copy(Profile *p)
{
	Profile *np  = calloc(1,sizeof(Profile));
	np->id = p->id;
	np->pairs = pair_dup(p->pairs);
	return np;
}
Profile *profile_find(char *user, char *group, char *rmtip, char *lclip) // return best matching profile... 
{
	// Find the last matching profile
	Profile *p,*lastp;
	for (p=list;p!=NULL;p=p->next) {
		if (!lib_match_list(pair_find(p->pairs,"users"),user)) continue;
		if (!lib_match_list(pair_find(p->pairs,"groups"),group)) continue;
		if (!lib_match_list(pair_find(p->pairs,"ips"),rmtip)) continue;
		if (!lib_match_list(pair_find(p->pairs,"bound"),lclip)) continue;
		lastp = p;
	}
	return profile_copy(lastp);
}
int profile_free(Profile **pp, char *whence)
{
	Profile *p = *pp;
	if (p==NULL) return TRUE;
	pair_free(&p->pairs);
	free(p);
	return TRUE;
}
int profile_replace(Profile *rep)
{
	Profile *p;
	int id=0;
	Profile **last = &list;
	for (p=list;p!=NULL;p=p->next) {
		printf("profile replace %d\n",p->id);
		if (p->id==rep->id) {
			*last = rep;
			rep->next = p->next;
			profile_free(&p,"replace");
			return TRUE;
		}
		if (id<p->id) id = p->id;
		last = &p->next;
	}
	rep->id = ++id;
	printf("profile_replace %d not found, so adding one\n",rep->id);
	// Need to add it:
	profile_append(rep);


	return FALSE;
}
int profile_save(char *fname)
{
	FILE *f;
	Profile *p;
	char tmpname[BFSZ];
	printf("profile_save(%s)\n",fname);
	lprintf(tmpname,BFSZ-1,"%s_new",fname);
	f = fopen(tmpname,"w");
	if (f==NULL) {
		printf("Unable to write profile (%s) %s\n",tmpname,strerror(errno));
		return FALSE;
	}

	for (p=list;p!=NULL;p=p->next) {
		Pair *v;
		fprintf(f,"profile|%s\n",profile_get(p,"profile"));
		for (v=p->pairs;v!=NULL;v=v->next) {
			if (strcmp(v->var,"profile")==0) continue; 
			fprintf(f,"%s|%s\n",v->var,v->val);
		}
	}
	if (fclose(f)!=0) {
		printf("profile: fclose failed\n");
		return FALSE;
	}
	remove(fname);
	if (rename(tmpname,fname)!=0) {
		printf("profile: rename failed %s\n",strerror(errno));
		return FALSE;
	}
	printf("Profile: stored ok (%s)\n",fname);
	return TRUE;

}