/* $Id: friend.c,v 1.2 2002/03/09 10:34:58 in2 Exp $ */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/file.h>
#include "config.h"
#include "pttstruct.h"
#include "common.h"
#include "perm.h"
#include "proto.h"

extern char currboard[];	/* name of currently selected board */
extern char *fn_overrides;
extern userinfo_t *currutmp;
extern char *fn_reject;
extern int usernum;
extern char *str_space;
extern char *msg_uid;

/* ------------------------------------- */
/* �S�O�W��                              */
/* ------------------------------------- */

/* Ptt ��L�S�O�W�檺�ɦW */
static char special_list[] = "list.0";
static char special_des[] = "ldes.0";

/* �S�O�W�檺�W�� */
static unsigned int friend_max[8] = {
    MAX_FRIEND,
    MAX_REJECT,
    MAX_LOGIN_INFO,
    MAX_POST_INFO,
    MAX_NAMELIST,
    MAX_NAMELIST,
    MAX_NAMELIST,
    MAX_NAMELIST
};
/* ���M�n�͸��a�H�W�泣�O * 2 ���O�@���̦hload��shm�u�঳128 */

/* Ptt �U�دS�O�W�檺�ɦW */
char *friend_file[8] = {
    FN_OVERRIDES,
    FN_REJECT,
    "alohaed",
    "postlist",
    "",
    FN_CANVOTE,
    FN_WATER,
    FN_VISABLE
};

/* Ptt �U�دS�O�W�檺�ɭz */
static char *friend_desc[8] = {
    "�ͽ˴y�z�G",
    "�c�δc���G",
    "",
    "",
    "�y�z�@�U�G",
    "�벼�̴y�z�G",
    "�c�δc���G",
    "�ݪO�n�ʹy�z"
};

/* Ptt �U�دS�O�W�檺����ԭz */
static char *friend_list[8] = {
    "�n�ͦW��",
    "�a�H�W��",
    "�W�u�q��",
    "�s�峹�q��",
    "�䥦�S�O�W��",
    "�p�H�벼�W��",
    "�ݪO�T�n�W��",
    "�ݪO�n�ͦW��"
};

static void setfriendfile(char *fpath, int type) {
    if (type <= 4)		/* user list Ptt */
	setuserfile(fpath, friend_file[type]);
    else			/* board list */
	setbfile(fpath, currboard, friend_file[type]);
}

static int friend_count(char *fname) {
    FILE *fp;
    int count = 0;
    char buf[200];

#if 0
    if ((fp = fopen(fname, "r")))
	while (fgets(buf, 200, fp))
	    count++;
#endif

/*rocker.011018: �ѰO���ɤF... */
    if ((fp = fopen(fname, "r")))
    {
      while (fgets(buf, 200, fp)) count++;
      fclose (fp);
    }
    
    return count;
}

void friend_add(char *uident, int type) {
    char fpath[80];

    setfriendfile(fpath, type);
    if (friend_count(fpath) > friend_max[type])
	return;

    if ((uident[0] > ' ') && !belong(fpath, uident))
    {
	FILE *fp;
	char buf[40] = "";
	char t_uident[IDLEN + 1];

    /* Thor: avoid uident run away when get data */
	strcpy(t_uident, uident);

	if (type != FRIEND_ALOHA && type != FRIEND_POST)
	    getdata(2, 0, friend_desc[type], buf, 40, DOECHO);

	if ((fp = fopen(fpath, "a")))
	{
	    flock(fileno(fp), LOCK_EX);
	    fprintf(fp, "%-13s%s\n", t_uident, buf);
	    flock(fileno(fp), LOCK_UN);
	    fclose(fp);
	}
    }
}

static void friend_special() {
    char genbuf[70], i, fname[70];

    friend_file[FRIEND_SPECIAL] = special_list;
    for (i = 0; i <= 9; i++)
    {
	sprintf(genbuf, "  (\033[36m%d\033[m)  .. ", i);
	special_des[5] = i + '0';
	setuserfile(fname, special_des);
	if (dashf(fname))
	{
	/* no NULL check?? */
	    FILE *fp = fopen(fname, "r");

	    fgets(genbuf + 15, 40, fp);
	    genbuf[47] = 0;
	}
	move(i + 12, 0);
	clrtoeol();
	outs(genbuf);
    }
    getdata(22, 0, "�п�ܲĴX���S�O�W�� (0~9)[0]?", genbuf, 3, LCECHO);
    if (genbuf[0] >= '0' && genbuf[0] <= '9')
    {
	special_list[5] = genbuf[0];
	special_des[5] = genbuf[0];
    }
    else
    {
	special_list[5] = '0';
	special_des[5] = '0';
    }
}

static void friend_append(int type, int count) {
    char fpath[80], i, j, buf[80], sfile[80];
    FILE *fp, *fp1;

    setfriendfile(fpath, type);

    do
    {
	move(2, 0);
	clrtobot();
	outs("�n�ޤJ���@�ӦW��?\n");
	for (i = 0, j = 0; i <= 7; i++)
	{
	    if (i == type)
		continue;
	    j++;
	    if (i <= 4)
		sprintf(buf, "  (%d) %-s\n", j, friend_list[(int) i]);
	    else
		sprintf(buf, "  (%d) %s ���� %s\n", j, currboard,
			friend_list[(int) i]);
	    outs(buf);
	}
	outs("  (S) ��ܨ�L�ݪO���S�O�W��");
	getdata(11, 0, "�� �� ����[Enter] ���:", buf, 3, LCECHO);
	if (!buf[0])
	    return;
	if (buf[0] == 's')
	    Select();
    }
    while (buf[0] < '1' || buf[0] > '9');

    j = buf[0] - '1';
    if (j >= type)
	j++;
    if (j == FRIEND_SPECIAL)
	friend_special();

    setfriendfile(sfile, j);

    fp = fopen(sfile, "r");
    while (fgets(buf, 80, fp) && count <= friend_max[type])
    {
	char the_id[15];

	sscanf(buf, "%s", the_id);
	if (!belong(fpath, the_id))
	{
	    if ((fp1 = fopen(fpath, "a")))
	    {
		flock(fileno(fp1), LOCK_EX);
		fputs(buf, fp1);
		flock(fileno(fp1), LOCK_UN);
		fclose(fp1);
	    }
	}
    }
    fclose(fp);
}

void friend_delete(char *uident, int type) {
    FILE *fp, *nfp;
    char fn[80], fnnew[80];
    char genbuf[200];

    setfriendfile(fn, type);

    sprintf(fnnew, "%s-", fn);
    if ((fp = fopen(fn, "r")) && (nfp = fopen(fnnew, "w")))
    {
	int length = strlen(uident);

	while (fgets(genbuf, STRLEN, fp))
	    if ((genbuf[0] > ' ') && strncmp(genbuf, uident, length))
		fputs(genbuf, nfp);
	fclose(fp);
	fclose(nfp);
	Rename(fnnew, fn);
    }
}

static void friend_editdesc(char *uident, int type) {
    FILE *fp, *nfp;
    char fnnew[200], genbuf[200], fn[200];
    setfriendfile(fn, type);
    sprintf(fnnew, "%s-", fn);
    if ((fp = fopen(fn, "r")) && (nfp = fopen(fnnew, "w")))
    {
	int length = strlen(uident);

	while (fgets(genbuf, STRLEN, fp))
	{
	    if ((genbuf[0] > ' ') && strncmp(genbuf, uident, length))
		fputs(genbuf, nfp);
	    else if (!strncmp(genbuf, uident, length))
	    {
		char buf[50] = "";
		getdata(2, 0, "�ק�y�z�G", buf, 40, DOECHO);
		fprintf(nfp, "%-13s%s\n", uident, buf);
	    }
	}
	fclose(fp);
	fclose(nfp);
	Rename(fnnew, fn);
    }
}

void friend_load() {
    FILE *fp;
    int myfriends[MAX_FRIEND];
    int myrejects[MAX_REJECT];
    int friendcount, rejectedcount;
    char genbuf[200];

    memset(myfriends, 0, sizeof(myfriends));
    friendcount = 0;
    setuserfile(genbuf, fn_overrides);
    if ((fp = fopen(genbuf, "r")))
    {
	int unum;

	while (fgets(genbuf, STRLEN, fp) && friendcount < MAX_FRIEND - 1)
	    if (strtok(genbuf, str_space))
		if ((unum = searchuser(genbuf)))
		    myfriends[friendcount++] = unum;
	fclose(fp);
    }
    memcpy(currutmp->friend, myfriends, sizeof(myfriends));

    memset(myrejects, 0, sizeof(myrejects));
    rejectedcount = 0;
    setuserfile(genbuf, fn_reject);
    if ((fp = fopen(genbuf, "r")))
    {
	int unum;

	while (fgets(genbuf, STRLEN, fp) && rejectedcount < MAX_REJECT - 1)
	    if (strtok(genbuf, str_space))
		if ((unum = searchuser(genbuf)))
		    myrejects[rejectedcount++] = unum;
	fclose(fp);
    }
    memcpy(currutmp->reject, myrejects, sizeof(myrejects));
    if(currutmp->friendtotal) logout_friend_online();
    login_friend_online();
}

extern userec_t cuser;

static void friend_water(char *message, int type) { /* �s����y added by Ptt */
    char fpath[80], line[80], userid[IDLEN + 1];
    FILE *fp;

    setfriendfile(fpath, type);
    if ((fp = fopen(fpath, "r")))
	while(fgets(line, 80, fp)) {
	    userinfo_t *uentp;
	    int tuid;
	    
	    sscanf(line, "%s", userid);
	    if((tuid = searchuser(userid)) && tuid != usernum &&
	       (uentp = (userinfo_t *) search_ulist(tuid)) &&
               isvisible_uid(tuid))
		my_write(uentp->pid, message, uentp->userid, 1, NULL);
	}
    fclose(fp);
}

void friend_edit(int type) {
    char fpath[80], line[80], uident[20];
    int count, column, dirty;
    FILE *fp;
    char genbuf[200];

    if (type == FRIEND_SPECIAL)
	friend_special();
    setfriendfile(fpath, type);

    if (type == FRIEND_ALOHA || type == FRIEND_POST)
    {
	if (dashf(fpath))
	{
	    sprintf(genbuf, "/bin/cp %s %s.old", fpath, fpath);
	    system(genbuf);
	}
    }

    dirty = 0;
    while (1)
    {
	stand_title(friend_list[type]);
	move(0, 40);
	sprintf(line, "(�W��W��:%d�ӤH)", friend_max[type]);
	outs(line);
	count = 0;
	CreateNameList();

	if ((fp = fopen(fpath, "r")))
	{
	    move(3, 0);
	    column = 0;
	    while (fgets(genbuf, STRLEN, fp))
	    {
		if (genbuf[0] <= ' ')
		    continue;
		strtok(genbuf, str_space);
		AddNameList(genbuf);
		prints("%-13s", genbuf);
		count++;
		if (++column > 5)
		{
		    column = 0;
		    outc('\n');
		}
	    }
	    fclose(fp);
	}
	getdata(1, 0, (count ?
		       "(A)�W�[(D)�R��(E)�ק�(P)�ޤJ(L)�ԲӦC�X"
		       "(K)�R����ӦW��(W)����y(Q)�����H[Q]" :
		       "(A)�W�[ (P)�ޤJ��L�W�� (Q)�����H[Q]"),
		uident, 3, LCECHO);
	if (*uident == 'a')
	{
	    move(1, 0);
	    usercomplete(msg_uid, uident);
	    if (uident[0] && searchuser(uident) && !InNameList(uident))
	    {
		friend_add(uident, type);
		dirty = 1;
	    }
	}
	else if (*uident == 'p')
	{
	    friend_append(type, count);
	    dirty = 1;
	}
	else if (*uident == 'e' && count)
	{
	    move(1, 0);
	    namecomplete(msg_uid, uident);
	    if (uident[0] && InNameList(uident))
	    {
		friend_editdesc(uident, type);
	    }
	}
	else if (*uident == 'd' && count)
	{
	    move(1, 0);
	    namecomplete(msg_uid, uident);
	    if (uident[0] && InNameList(uident))
	    {
		friend_delete(uident, type);
		dirty = 1;
	    }
	}
	else if (*uident == 'l' && count)
	    more(fpath, YEA);
	else if (*uident == 'k' && count)
	{
	    getdata(2, 0, "����W��N�|�Q�R��,�z�T�w�� (a/N)?", uident, 3,
		    LCECHO);
	    if (*uident == 'a')
		unlink(fpath);
	    dirty = 1;
	}
	else if (*uident == 'w' && count)
	{
	    if (!getdata(0, 0, "�s����y:", uident, 60, DOECHO))
		continue;
	    if (getdata(0, 0, "�T�w��X�s����y? [Y]", line, 4, LCECHO) &&
		*line == 'n')
		continue;
	    friend_water(uident, type);
	}
	else
	    break;
    }
    if (dirty)
    {
	move(2, 0);
	outs("��s��Ƥ�..�еy��.....");
	refresh();
	if (type == FRIEND_ALOHA || type == FRIEND_POST)
	{
	    sprintf(genbuf, "%s.old", fpath);
	    if ((fp = fopen(genbuf, "r")))
	    {
		while (fgets(line, 80, fp))
		{
		    sscanf(line, "%s", uident);
		    sethomefile(genbuf, uident,
			  type == FRIEND_ALOHA ? "aloha" : "postnotify");
		    del_distinct(genbuf, cuser.userid);
		}
		fclose(fp);
	    }
	    sprintf(genbuf, "%s", fpath);
	    if ((fp = fopen(genbuf, "r")))
	    {
		while (fgets(line, 80, fp))
		{
		    sscanf(line, "%s", uident);
		    sethomefile(genbuf, uident,
			  type == FRIEND_ALOHA ? "aloha" : "postnotify");
		    add_distinct(genbuf, cuser.userid);
		}
		fclose(fp);
	    }
	}
	else if (type == FRIEND_SPECIAL)
	{
	    genbuf[0] = 0;
	    setuserfile(line, special_des);
	    if ((fp = fopen(line, "r")))
	    {
		fgets(genbuf, 30, fp);
		fclose(fp);
	    }
	    getdata_buf(2, 0, " �Ь����S�O�W����@��²�u�W��:", genbuf, 30,
			DOECHO);
	    if ((fp = fopen(line, "w")))
	    {
		fprintf(fp, "%s", genbuf);
		fclose(fp);
	    }
	}
	friend_load();
    }
}

int t_override() {
    friend_edit(FRIEND_OVERRIDE);
    return 0;
}

int t_reject() {
    friend_edit(FRIEND_REJECT);
    return 0;
}