#include "includes.h"

bool irc_connect(irc_cfg_t *icfg)
{
	char *buf;
	bool ret;
	int tmp;

	if(!icfg) return false;
	buf = malloc(strlen(icfg->nick)+strlen(icfg->host)+CS_LIM+1);
	if(!buf) return false;
	ret = true;

	tmp = sprintf(buf, "NICK %s\r\n"
			"USER %s cyberspace %s :cyberstorm\r\n",
			icfg->nick, icfg->nick, icfg->host);

	icfg->net_ctx.host = icfg->host;
	icfg->net_ctx.port = icfg->port;
	if(!contcp_connect(&icfg->net_ctx))
		fail(ret, false, c);
	if(nsend(&icfg->net_ctx, buf, tmp) != tmp)
		fail(ret, false, c);

c:
	if(buf) free(buf);
	return ret;
}

bool irc_join_part(irc_cfg_t *icfg, char *channel, bool join)
{
	char buf[CS_LIM+16];
	int tmp;

	if(!icfg || !channel)
		return false;
	tmp = sprintf(buf, "%s %s%s\r\n",
			join?"JOIN":"PART",
			channel[0]=='#'?"":"#",
			channel);

	if(nsend(&icfg->net_ctx, buf, tmp) != tmp)
		return false;

	return true;
}

char *irc_fetchln(irc_cfg_t *icfg, char *lin, size_t lin_len)
{
	char *ret;
	int i;

	ret = realloc(lin, CS_LIM+lin_len+1);
	if(!ret) return NULL;

	i = nrecv(&icfg->net_ctx, ret+lin_len, CS_LIM);
	if(i <= 0) {
		free(ret);
		return NULL;
	}
	*(ret+lin_len+i) = '\0';

	if(!strchr(ret+lin_len, '\n'))
		return irc_fetchln(icfg, ret, lin_len+i);

	return ret;
}

bool irc_send(irc_cfg_t *icfg, char *dst, char *msg)
{
	bool ret;
	char *buf;
	int tmp;

	if(!icfg || !dst || !msg)
		return false;

	buf = malloc(strlen(dst)+strlen(msg)+32);
	if(!buf) return false;

	ret = true;
	tmp = sprintf(buf, "PRIVMSG %s :%s\r\n", dst, msg);
	if(nsend(&icfg->net_ctx, buf, tmp) != tmp)
		ret = false;

	free(buf);
	return ret;
}

char *irc_retr_sender(irc_cfg_t *icfg, char *buf)
{
	char *ret, *tmp;

	if(!icfg || !buf)
		return NULL;
	tmp = strchr(buf, '!');
	if(!tmp) return NULL;
	*tmp = '\0';
	ret = strdup(buf+1);
	*tmp = '!';

	return ret;
}

bool irc_cmd(irc_cfg_t *icfg, char *buf)
{
	size_t buflen;
	char *cmd, *tmp, *sender;

	if(!icfg || !buf)
		return false;

	tmp = strstr(buf, "PRIVMSG");
	if(!tmp) return false;
	buflen = strlen(tmp);
	cmd = malloc(buflen+1);
	if(!cmd) return false;
	if(sscanf(tmp, "PRIVMSG %*s :%[^\r\n]", cmd) != 1) {
		free(cmd);
		return false;
	}

	sender = irc_retr_sender(icfg, buf);
	if(!sender) {
		free(cmd);
		return false;
	}
	
	// look up cmd
	irc_exec(icfg, sender, cmd);

	free(sender);
	free(cmd);

	return true;
}

bool irc_proc(irc_cfg_t *icfg)
{
	char *buf;

	if(irc_connect(icfg) == false)
		return false;
	if(irc_join_part(icfg, icfg->channel, true) == false)
		return false;
	while(buf = irc_fetchln(icfg, NULL, 0)) {
		if(!strncasecmp(buf, "PING", 4)) {
			buf[1] = 'O';
			nsend(&icfg->net_ctx, buf, strlen(buf));
		} else irc_cmd(icfg, buf);
		free(buf);
	}

	return true;
}

void irc_drop(irc_cfg_t *icfg, char *qmesg)
{
	char buf[CS_LIM+1];
	int tmp;

	tmp = sprintf(buf, "QUIT %s\r\n", qmesg);
	nsend(&icfg->net_ctx, buf, tmp);
	contcp_close(&icfg->net_ctx);
}
