#include "Cache.h"
#include "SubLang.h"

char cache;
char cacherule;
char *pwd;
char *tmp;

void cache_init(void)
{
	char *pwd;
	char *hsml_tmp;
	char *cache_str = getenv("HSML_CACHE");
	char *cacherule_str = getenv("HSML_CACHERULE");
	
	if(!cache_str) cache = CACHE_BOTH;
	else if(!strcmp(cache_str, "exec")) cache = CACHE_EXEC;
	else if(!strcmp(cache_str, "output")) cache = CACHE_OUTPUT;
	else cache = CACHE_BOTH;
		
	if(!cacherule_str) cacherule = CACHERULE_NEVER;
	else if(!strcmp(cacherule_str, "time")) cacherule = CACHERULE_TIME;
	else if(!strcmp(cacherule_str, "noinput")) cacherule = CACHERULE_NOINPUT;
	else cacherule = CACHERULE_NEVER;
	
	hsml_tmp = getenv("HSML_TMP");
	if(hsml_tmp[0] == '/') tmp = hsml_tmp;
	else {
		pwd = getcwd(NULL, 0);
		tmp = (char*)malloc(strlen(pwd) + strlen(hsml_tmp) + 2);
		sprintf(tmp, "%s/%s", pwd, hsml_tmp);
	}
	free(pwd);
}

bool cache_should_output(char *path)
{
	struct stat fileinfo, cacheinfo;
	char *cachepath;
		
	if(cacherule == CACHERULE_NEVER) return false;
	if(cacherule == CACHERULE_TIME && (cache == CACHE_OUTPUT || cache == CACHE_BOTH) || !strcmp(getenv("ARGS"),""))
	{
		stat(path, &fileinfo);
		cachepath = (char*)malloc(strlen(tmp) + sizeof(CACHE_DIR_HTML) + strlen(path) + 3);
		sprintf(cachepath, "%s/%s/%s", tmp, CACHE_DIR_HTML, path);
		if(stat(cachepath, &cacheinfo) == -1) return false;
		free(cachepath);
		
		if(fileinfo.st_mtime < cacheinfo.st_mtime) return true;
	}
	return false;	
}

bool cache_should_exec(char *path)
{
	struct stat fileinfo, cacheinfo;
	char *cachepath;

	if(cacherule == CACHERULE_NEVER) return false;
	if(cache == CACHE_EXEC || cache == CACHE_BOTH)
	{
		stat(path, &fileinfo);
		cachepath = (char*)malloc(strlen(tmp) + sizeof(CACHE_DIR_EXE) + strlen(path) + 3);
		sprintf(cachepath, "%s/%s/%s", tmp, CACHE_DIR_EXE, path);
		if(stat(cachepath, &cacheinfo) == -1) return false;
		free(cachepath);
		
		if(fileinfo.st_mtime < cacheinfo.st_mtime) return true;
	}
	return false;
}

void cache_print(char *path)
{
	FILE *fd;
	char *buf;
	long filesize;
	char *cachepath = (char*)malloc(strlen(tmp) + sizeof(CACHE_DIR_HTML) + strlen(path) + 3);
	sprintf(cachepath, "%s/" CACHE_DIR_HTML "/%s", tmp, path);
	fd = fopen(cachepath, "r");
	free(cachepath);
	if(!fd){
		perror("Could not open cache file for read");
		return;
	}
	fseek(fd, 0, SEEK_END);
	filesize = ftell(fd);
	buf = (char*)malloc(filesize);
	fseek(fd, 0, SEEK_SET);
	fread(buf, filesize, 1, fd);
	fclose(fd);
	write(1,buf, filesize);
	free(buf);
}

void cache_output_add(char *output, char *path)
{
	char *dest = (char*)malloc(strlen(tmp) + sizeof(CACHE_DIR_HTML) + strlen(path) + 3);
	
	sprintf(dest, "%s/" CACHE_DIR_HTML "/%s", tmp, path);
	if(!cache_makedir_r(dest)) return;
	
	if(rename(output, dest)) unlink(output);
	
	free(dest);
}

void cache_exec_add(char *exe, char *path)
{
	char *dest = (char*)malloc(strlen(tmp) + sizeof(CACHE_DIR_EXE) + strlen(path) + 3);
	
	sprintf(dest, "%s/" CACHE_DIR_EXE "/%s", tmp, path);
	if(!cache_makedir_r(dest)) return;

	if(rename(exe, dest)) unlink(exe);
	
	free(dest);
}

void cache_exec(char *exe, int lang)
{
	sublang[lang].cache_exec(exe, tmp);

	/* XXX type another message ;) */
	printf("Error executing script. Check language environs with '-l\n");
	sublang[lang].show_config();
	perror("PERROR MSG: ");
}

bool cache_makedir_r(char *path)
{
	char *next;
	char *current_dir = (char *)calloc(strlen(path) + 1, 1);
	struct stat fileinfo;
	
	do {
		next = strchr(path + strlen(current_dir) + 1, '/');
		if(!next) return true;
		memcpy(current_dir, path, next - path);
	} while(!stat(current_dir, &fileinfo));
	
	if(mkdir(current_dir, 0700)) return false;
	while(strlen(current_dir) != strlen(path))
	{
		next = strchr(path + strlen(current_dir) + 1, '/');
		if(!next) return true;
		memcpy(current_dir, path, next - path);
		if(mkdir(current_dir, 0700)) return false;
	}
	free(current_dir);
	return true;
}
