// ------------------------------------------------------------------------------------------------
// DESCRIPTION  Multiple identity code as used by surgeweb and surgealert
// ------------------------------------------------------------------------------------------------
// NOTES
// ------------------------------------------------------------------------------------------------
#ifdef __XCODE__
#include "xcode_quiet.h"
#endif

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include "tcplib.h"
#include "smail.h"
#include "lprintf.h"
#include "lib.h"
#include "identity.h"
#define DMID 4
#include "dmalloc.h"
#include "string_hide.h"

int imsg(const char * arg_list, ...);


Identity *identity_new(char *name)
{
	Identity *l=NULL;
	l=calloc(1,sizeof(Identity));
	if (!l) return NULL;
	return l;
}
void identity_free(Identity **l)
{
	if(*l==NULL) return;
	ffree((*l)->type);
	ffree((*l)->name);
	ffree((*l)->email);
	ffree((*l)->data);
	pair_free(&(*l)->param);
	ffree(*l);
}
void identity_freeall(Identity** list)
{
	Identity *l,*next;
	if (!list || !*list) return;
	for(l=*list;l;l=next){
		next=l->next;
		identity_free(&l);
	}
	*list=NULL;
}
int identity_add_atend(Identity **list, Identity *ident)
{
	Identity *l,*end=NULL;
	for (l=*list;l!=NULL;l=l->next) end = l;
	if(end){
		end->next=ident;
	}else{
		*list=ident;
	}
	return TRUE;
}
Identity *identity_find(Identity *identities, int id)
{
	Identity *l=NULL;
	for(l=identities;l;l=l->next){
		if(l->id==id)
			break;
	}
	return l;
}
Identity *identity_find_email(Identity *identities, char* email)
{
	Identity *l=NULL;
	for(l=identities;l;l=l->next){
		if(strcmp(l->type,"self")==0) continue;
		if(strcmp(l->email,email)==0)
			break;
	}
	return l;
}
Identity *identity_blank(Identity *identities)
{
	Identity *ident;
	int id,n=0;
	ident=identity_new(NULL);
	id=myrand()%90000+10;
	while(identity_find(identities,id)){
		id++;n++;
		if(id>90000) id=10;
		if(n>90000) {free(ident);return NULL;}
	}
	ident->id=id;
	return ident;
}
int identity_load(Identity** list, char* fname)	// cf sw_labels_load
{
	char bf[BFSZ],tmp[BFSZ],*p,*s;
	FILE *f;
	Identity *l=NULL;
	int valid=FALSE;
	char *names[100],*values[100];
	int n,i,count=0;

	imsg("sw_identity_loadfile(%s)\n",fname);
	f = fopen(fname,"r");
	if (!f) return FALSE;
	while(fgets(bf,BFSZ,f)) {
		// read file
		lib_strip_crlf(bf);
		if (bf[0]=='#') continue;
		for(p = bf; sisspace(*p); p++);
		if (*p==0) continue;
		if (count>90) continue;	// maybe limit some more sometime

		l=identity_new("");
		if (!l) {ffree(l); continue;}
		l->id=atoi(p); p=strchr(p,'|');
		if(!p||!*(p+1)) {ffree(l); continue;}
		s=p+1; p=strchr(p+1,'|');
		if(!p||!*(p+1)) {ffree(l); continue;}
		*p=0; l->type=strdup(s); s=p+1; p=strchr(p+1,'|');
		if(!p||!*(p+1)) {ffree(l); continue;}
		*p=0; l->email=strdup(s); s=p+1; p=strchr(p+1,'|');
		if(!p/*||!*(p+1)*/) {ffree(l); continue;}
		*p=0;l->name=strdup(s);
		p++;
		if(strstr(p,"=\"") || lib_strlen(p)==0){
			ncpy(tmp,p,BFSZ-1);
		}else{
			string_unhide(p,tmp,BFSZ,FALSE);
		}

		n=lib_token_split_quoted(tmp,names,values,100);
		for(i=0;i<n;i++){
			pair_add_atend(&l->param,names[i],values[i]);
		}
		if(strcmp(l->type,"self")==0){
			lprintf(bf,BFSZ,"%d",9);
			pair_add_atend(&l->param,"icon",bf);
		}
		// add it
		identity_add_atend(list,l);
		count++;
	}
	fclose(f); f=NULL;
	imsg("surgeweb %d identities loaded",count);
	return TRUE;
}
int identity_save(Identity* identities, char *fname)
{
	Identity *l;
	Pair *p;
	char fname_old[BFSZ],fname_tmp[BFSZ],bf[BFSZ],tmp[BFSZ],tmp2[BFSZ];
	FILE *f;
	int count=0;
	lprintf(fname_old,BFSZ,"%s_old",fname);
	lprintf(fname_tmp,BFSZ,"%s_tmp",fname);
	f=fopen(fname_tmp,"wb");
	if(!f) return FALSE;

	for (l=identities;l;l=l->next){
		if(l->del) continue;
		*bf=0;
		for(p=l->param;p;p=p->next){
			if(lib_strlen(p->val)==0) continue;
			lprintf(tmp,BFSZ,"%s=\"%s\"",p->var,lib_encode_quoteonly(tmp2,p->val,BFSZ-1));
			ncat_sep(bf," ",tmp,BFSZ-1);
		}
		if(FALSE){
			ncpy(tmp,bf,BFSZ-1);
		}else{
			string_hide(bf,tmp,BFSZ,FALSE);
		}
		lprintf(bf,BFSZ,"%05d|%s|%s|%s|%s",l->id,l->type,l->email,l->name,tmp);
		fprintf(f,"%s\n\n",bf);
		count++;
	}
	fclose(f);
	remove(fname_old);
	rename(fname,fname_old);
	rename(fname_tmp,fname);
	remove(fname_old);

	imsg("surgeweb %d identities saved",count);
	return TRUE;
}

int identity_findmove(Identity *identities)
{
	Identity *l,*l_last=NULL;
	int track=FALSE;

	// Show tags to move them
	for(l=identities;l;l=l->next){
		l->move=0;
		if(l->del) continue;
		if(strcmp(l->type,"self")==0) continue;
		if(track){
			l_last->move++;
			l->move++;
		}
		l_last=l;
		track=TRUE;
	}
	if(l_last && l_last->move) l_last->move=3;
	return TRUE;
}
int identity_move(Identity *identities, int ident, int dir)
{
	Identity *list[100],*l,*l2;
	int tot=0,i;

	identity_findmove(identities);

	for(l=identities;l;l=l->next){
		if (tot>90) continue;	// maybe limit some more sometime
		list[tot]=l;
		tot++;
	}
	for(i=0;i<tot;i++){
		l=list[i];
		if(l->id!=ident) continue;
		if(dir<0 && (l->move==1 || l->move==2) && (i<tot-1)){	// Move down
			l2=list[i];
			list[i]=list[i+1];
			list[i+1]=l2;
			break;
		}
		if(dir>0 && (l->move==2 || l->move==3) && (i>0)){		// Move up
			l2=list[i];
			list[i]=list[i-1];
			list[i-1]=l2;
			break;
		}
	}
	for(i=0;i<tot;i++){
		l=list[i];
		if(i<tot-1){
			l->next=list[i+1];
		}else{
			l->next=NULL;
		}
	}
	return TRUE;
}
int identity_count(Identity *identities)
{
	Identity *ident;
	int n=0;
	if (!identities) return 0;
	for(ident=identities;ident;ident=ident->next){
		if(ident->del)continue;
		n++;
	}
	return n;
}

