#include "spam_check.h"
#include "config.h"
#include "smtpd.h"
#include "cats.h"
#include "btree.h"
#include "clamav.h"
#include <math.h>

//extern struct rules_t baserules[BASERULES];
extern struct rules_master rules;
extern struct settings global;
int av_scan(const char *filename, const char **virname);


int spam_check(char *user,struct message *msg) {
	int i,ret;
	FILE *fd;
	char buf[1024];
	char *fullbuf;
	//unsigned long long tag,reject;
	struct u_node *us;
	struct stat sb;
	const char *virname;
	struct {
		char *header;
		char *text;
		char *html;
	} *pieces;

	us = find_str(user);
	if (us == NULL) {
		printf("no settings found, using defaults.\n");
	} else
		printf("%s == user settings\n", us->user);
	stat(msg->filename,&sb);
	//printf("blocks: %ld, blocksize: %u, size: %ld\n",(long)sb.st_blocks, sb.st_blksize,(long)sb.st_size);
	if (sb.st_size > global.maxmessagesize)
		return -1000; //whoops, too large

	fullbuf = xmalloc(sb.st_size + 1);

	fd = fopen(msg->filename,"r");
	while (fgets(buf,sizeof(buf),fd)){
		strcat(fullbuf,buf);
	}
	fclose(fd);

	
	if (check_rule(ATTACH,fullbuf,rules.baserules[ATTACH].handler,rules.baserules[ATTACH].extra)) {
		printf("ATTACHMENT detected\n");
		if (us->tag & CAT_AV || us->reject & CAT_AV)
			if ((ret = av_scan(msg->filename, &virname)) == CL_VIRUS) {
				printf("%s detected",virname);
				if (us->tag & CAT_AV) {
					add_subject(msg,"[VIRUS] - ");
					return 0;
				}
				if (us->reject & CAT_AV) {
					return -1001;
				}
			}
	}
	if (!(check_rule(WWW,fullbuf,rules.baserules[WWW].handler,rules.baserules[WWW].extra))) {
		printf("no link detected\n");
		free(fullbuf);
		return 0;
	}
	//printf("%s\n",fullbuf);
//	if (i == 0) {
//		free(fullbuf);
//		return -1;
//	}

	if (!(check_rule(WWW,fullbuf,rules.baserules[WWW].handler,rules.baserules[WWW].extra))) {
		printf("no link detected\n");
		free(fullbuf);
		return 0;
	}

	for (i=0;i<rules.bodycount;i++) {
		if (check_rule(i,fullbuf,rules.body[i].handler,rules.body[i].extra)) {
			printf("Matching Body rule: %d - %s \n",i,rules.body[i].description);
			msg->score += rules.body[i].score;
			msg->result[rules.body[i].class] += rules.body[i].score;
			//printf("found match, class %d\n",rules.body[i].class);
		}
	}
	for (i=0;i<rules.headercount;i++) {
		if (check_rule(i,fullbuf,rules.header[i].handler,rules.header[i].extra)) {
			printf("matching header rule: %d - %s \n",i,rules.header[i].description);
			msg->score += rules.header[i].score;
			msg->result[rules.header[i].class] += rules.header[i].score;
			//printf("found match, class %d\n",rules.body[i].class);
		}
	}

	// html
	if (check_rule(HTML,fullbuf,rules.baserules[HTML].handler,rules.baserules[HTML].extra)) {
		printf("html detected\n");
		for (i=0;i<rules.htmlcount;i++) {
			if (check_rule(i,fullbuf,rules.html[i].handler,rules.html[i].extra)) {
				printf("matching html rule: %d - %s \n",i,rules.html[i].description);
				msg->score += rules.html[i].score;
				msg->result[rules.html[i].class] += rules.html[i].score;
				//printf("found match, class %d\n",rules.body[i].class);
			}
		}
	}

	free(fullbuf);

	short largest=0;

	if (msg->result[10] > 20) { //10 == OFFER
		printf("gen spam (%d) > 20\n",msg->result[10]);
		for (i=0;i<CAT_NUM;i++) {
			if ((msg->result[largest] < msg->result[i]) && (i != 10)){
				printf("i = %d %d > old latest= %d %d\n",i,msg->result[i],largest,msg->result[largest]);
				largest=i;
			}
		}
	}
	switch (1<<(largest-1))
	{
	case CAT_MED:
		printf("Email probably Meds\n");
		break;	
	case CAT_WORK:
		printf("Email probably Work at home\n");
		break;	
	case CAT_WEIGHT:
		printf("Email probably Weightloss\n");
		break;	
	case CAT_STOCK:
		printf("Email probably Stocks\n");
		break;	
	case CAT_LOAN:
		printf("Email probably Loan/debt/mortgage\n");
		break;	
	case CAT_COMPUTER:
		printf("Email probably PC\n");
		break;	
	case CAT_DATING:
		printf("Email probably Dating\n");
		break;	
	case CAT_COLLEGE:
		printf("Email probably College\n");
		break;	
	case CAT_ADULT:
		printf("Email probably adult\n");
		break;	
	case CAT_OFFER:
		printf("Email general spam.\n");
		break;	
	}
	return largest;
};

/*

int bin(unsigned long long x){
	int i;
	unsigned long long z=x;
	for (i=0;i<64;i++) {
		printf("%d",z & 1);
		z = z >> 1;
	}
	printf(" - %llu\n",x);
	return 0;
}


