#include "std.h"
#include "dat.h"

Ring ring;

Key*
keyiterate(int skip, char *fmt, ...)
{
	int i;
	Attr *a;
	Key *k;
	va_list arg;

	va_start(arg, fmt);
	a = parseattrfmtv(fmt, arg);
	va_end(arg);

	for(i=0; i<ring.nkey; i++){
		k = ring.key[i];
		if(matchattr(a, k->attr, k->privattr)){
			if(skip-- > 0)
				continue;
			k->ref++;
			freeattr(a);
			return k;
		}
	}
	freeattr(a);
	werrstr("no key found");
	return nil;
}

Key*
keylookup(char *fmt, ...)
{
	int i;
	Attr *a;
	Key *k;
	va_list arg;

	va_start(arg, fmt);
	a = parseattrfmtv(fmt, arg);
	va_end(arg);

	for(i=0; i<ring.nkey; i++){
		k = ring.key[i];
		if(matchattr(a, k->attr, k->privattr)){
			k->ref++;
			freeattr(a);
			return k;
		}
	}
	freeattr(a);
	werrstr("no key found");
	return nil;
}

Key*
keyfetch(Conv *c, char *fmt, ...)
{
	int i, tag;
	Attr *a;
	Key *k;
	va_list arg;

	va_start(arg, fmt);
	a = parseattrfmtv(fmt, arg);
	va_end(arg);

	flog("keyfetch %A", a);
	tag = 0;

	for(i=0; i<ring.nkey; i++){
		k = ring.key[i];
		if(tag < k->tag)
			tag = k->tag;
		if(matchattr(a, k->attr, k->privattr)){
			k->ref++;
			if(strfindattr(k->attr, "confirm") && confirmkey(c, k) != 1){
				k->ref--;
				continue;
			}
			freeattr(a);
			flog("using key %A %N", k->attr, k->privattr);
			return k;
		}
	}

	if(needkey(c, a) < 0)
		convneedkey(c, a);

	for(i=0; i<ring.nkey; i++){
		k = ring.key[i];
		if(k->tag <= tag)
			continue;
		if(matchattr(a, k->attr, k->privattr)){
			k->ref++;
			if(strfindattr(k->attr, "confirm") && confirmkey(c, k) != 1){
				k->ref--;
				continue;
			}
			freeattr(a);
			return k;
		}
	}
	freeattr(a);
	werrstr("no key found");
	return nil;
}

static int taggen;

void
keyadd(Key *k)
{
	int i;

	k->ref++;
	k->tag = ++taggen;
	for(i=0; i<ring.nkey; i++){
		if(matchattr(k->attr, ring.key[i]->attr, nil)
		&& matchattr(ring.key[i]->attr, k->attr, nil)){
			keyclose(ring.key[i]);
			ring.key[i] = k;
			return;
		}
	}

	ring.key = erealloc(ring.key, (ring.nkey+1)*sizeof(ring.key[0]));
	ring.key[ring.nkey++] = k;
}

void
keyclose(Key *k)
{
	if(k == nil)
		return;

	if(--k->ref > 0)
		return;

	if(k->proto->closekey)
		(*k->proto->closekey)(k);

	freeattr(k->attr);
	freeattr(k->privattr);
	free(k);
}

Key*
keyreplace(Conv *c, Key *k, char *fmt, ...)
{
	Key *kk;
	char *msg;
	Attr *a, *b, *bp;
	va_list arg;

	va_start(arg, fmt);
	msg = vsmprint(fmt, arg);
	if(msg == nil)
		sysfatal("out of memory");
	va_end(arg);

	/* replace prompted values with prompts */	
	a = copyattr(k->attr);
	bp = parseattr(k->proto->keyprompt);
	for(b=bp; b; b=b->next){
		a = delattr(a, b->name);
		a = addattr(a, "%q?", b->name);
	}
	freeattr(bp);

	if(badkey(c, k, msg, a) < 0)
		convbadkey(c, k, msg, a);
	kk = keylookup("%A", a);
	freeattr(a);
	keyclose(k);
	if(kk == k){
		keyclose(kk);
		werrstr("%s", msg);
		return nil;
	}

	if(strfindattr(kk->attr, "confirm")){
		if(confirmkey(c, kk) != 1){
			werrstr("key use not confirmed");
			keyclose(kk);
			return nil;
		}
	}
	return kk;
}

void
keyevict(Conv *c, Key *k, char *fmt, ...)
{
	char *msg;
	Attr *a, *b, *bp;
	va_list arg;

	va_start(arg, fmt);
	msg = vsmprint(fmt, arg);
	if(msg == nil)
		sysfatal("out of memory");
	va_end(arg);

	/* replace prompted values with prompts */	
	a = copyattr(k->attr);
	bp = parseattr(k->proto->keyprompt);
	for(b=bp; b; b=b->next){
		a = delattr(a, b->name);
		a = addattr(a, "%q?", b->name);
	}
	freeattr(bp);

	if(badkey(c, k, msg, nil) < 0)
		convbadkey(c, k, msg, nil);
	keyclose(k);
}
