/* BitTorrentfs - a BitTorrent client file server */
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <fcall.h>
#include <thread.h> 
#include <9p.h>
#include <pool.h>
#include "torrent.h"
#include "torrentfile.h"
#include "misc.h"
#include "comm.h"

char mypeerid[PEERIDLEN+1];
char port[] = "6881";
char datadir[256];
int verbose = 0;
extern Srv fs;

void
setpeerid(void)
{
	/*
	peer id = 20 bytes = <"-p9btfs-"><12 random chars>
	*/
	char min = 48;
	char max = 122;
	double rn;
	char prefix[] = "-p9btfs-";
	long prefixsz = strlen(prefix);
	int suffixsz = PEERIDLEN - prefixsz;

	srand(time(0));
	strncpy(mypeerid, prefix, prefixsz);
	for (int i=0;i<suffixsz;i++){
		rn = min + frand() * (max - min);
		mypeerid[i+prefixsz] = (char)floor(rn);
	}
	mypeerid[PEERIDLEN] = '\0';
}

void
setdatadir(char *dir)
{
//	uchar length = strlen(dir);
//	datadir = emalloc(length+1);
	strcpy(datadir,dir);
}

char *
propername(Rune *name, uchar maxsize)
{
	char *buf;
	uchar namelen;

	/*
	pass 0 as a maxsize for no maxsize
	*/
	if ((namelen = runestrlen(name)) > maxsize && maxsize != 0)
		namelen = maxsize;
	buf = emalloc(namelen+1);
	for (int i=0; i<namelen; i++){
		runetochar(&(buf[i]),&(name[i]));	
		if (buf[i] == ' ')
			buf[i] = '-';
	}
	buf[namelen] = '\0';
	return buf;
}

void
tortotree(File *root, Torrent *tor)
{
	File *torrent;
	char *buf;
	File *parent;
	File *tracker;
	File *announce;
	File *files;

	buf = emalloc(2 * HASHSIZE + 1);
	for (int i=0; i<HASHSIZE; i++)
		sprint(&(buf[2*i]),"%.2ux", tor->infohash[i]);
	parent = root;
	incref(parent);
	parent = walkfile(parent, "torrents");
	if(parent == nil){
		free(buf);
		closefile(parent);
		return;
	}
	torrent = createfile(parent, buf, parent->uid, DMDIR|0644, nil);
	tracker = createfile(torrent, "tracker", torrent->uid, DMDIR|0644, nil);
	announce = createfile(tracker, "announce", tracker->uid, 0644, nil);
	files = createfile(torrent, "pieces", torrent->uid, DMDIR|0644, nil);
	/*
	files->aux = smprint("%s", "pieces");
	print("%s \n", files->aux);
	*/

	closefile(parent);
	free(buf);
}

void 
filltree(File *root)
{
	File *ctl;
	File *torrents;

	ctl = createfile(root, "ctl", root->uid, 0644, nil);
	torrents = createfile(root, "torrents", root->uid, DMDIR|0644, nil);
}

Torrent *
addtorrent(char *torrentfile)
{
	Torrent *tor = nil;
	int fd;

	print("Adding %s\n", torrentfile);
	tor = emalloc(sizeof(Torrent));
	parsebtfile(torrentfile, tor);
	tor->infohash = getinfohash(torrentfile, tor->infosize);
	tortotree(fs.tree->root, tor);

	/* create data files */
	tor->datafiles = emalloc(tor->filesnb * sizeof(char *));
	for (int i=0; i<tor->filesnb; i++){	
		tor->datafiles[i] = emalloc(strlen(datadir) + 1 + strlen(propername(tor->filepath[i], 0))+ 1);
		tor->datafiles[i] = strcpy(tor->datafiles[i], datadir);
		tor->datafiles[i] = strcat(tor->datafiles[i], "/");
		tor->datafiles[i] = strcat(tor->datafiles[i], propername(tor->filepath[i], 0));
		dbgprint("tor->datafiles[i]: %s\n", tor->datafiles[i]);
		fd = create(tor->datafiles[i],OEXCL,0600);
		close(fd);	
	}
	preppieceslist(tor);
	return tor;
}

void
leecher(void *arg)
{
	Peer *peer;
	char *msg;
	Torrent *tor;

	tor = arg;
	peer = emalloc(sizeof(Peer));
	msg = forgerequest(tor, "announce");
	if (calltracker(msg, peer) == -1)
		sysfatal("calltracker failed");
	callpeer(peer,tor);	
	free(msg);
	free(peer);
	free(tor);
	print("done leeching\n");
	threadexits(0); 
}

void
usage(void)
{
	fprint(2, "usage: btfs [-d datadir] [-m mntpt] ");
	exits("usage");
}

void
threadmain(int argc, char **argv)
{
	mainmem->flags |= POOL_PARANOIA;
	char *mtpt = "/mnt/btfs";
	char datadir[256];
	int userfd;
	char username[256];
	int namelen;
//	char *datadir = "/usr/glenda/torrents";
	Dir *dir;
	int fd;
	Torrent *tor;

	memset(username, 0, 256);
	userfd = open("/dev/user", OREAD);
	namelen=read(userfd, username, 256);
//	print("current user is %s\n", username);
	snprint(datadir, namelen +14, "/usr/%s/torrents", username);
	
	ARGBEGIN{
	case 'm':
		mtpt = ARGF();
		break;
	case 'd':
		snprint(datadir, 256, ARGF());
		break;
	case 'v':
		verbose = 1;
	default:
		break;
	}ARGEND

	if ((dir = dirstat(mtpt)) == nil) {
		print("%s does not exist, creating it. \n", mtpt);
		fd = create(mtpt,OREAD,DMDIR|0755);		
		close(fd);
	}
	free(dir);

//	print("datadir is %s\n", datadir);
	setdatadir(datadir);
	if ((dir = dirstat(datadir)) == nil) {
		print("%s does not exist, creating it. \n", datadir);
		fd = create(datadir,OREAD,DMDIR|0755);	
		close(fd);	
	}
	free(dir);

	fs.tree = alloctree(nil, nil, DMDIR|0777, nil);
	filltree(fs.tree->root);
	threadpostmountsrv(&fs, nil, mtpt, MREPL|MCREATE);
	setpeerid();
	/*
	tor = addtorrent("/usr/glenda/btfs.torrent");
	proccreate(leecher, tor, STACK);
	*/

	threadexits(0);
}

