#define BF_STACKLEN 30000

#include "HsmlLang.h"
#include "Cache.h"

#define _BF_NOMAIN_
#include "BrainFuck.c"


char lang[] = "brainfuck";
char file[] = ".bf.html";

bool init(void)
{
}

char *get_path_from_env(void)
{
}

void show_config(void)
{
	printf("Brainfuck hsml sublang module\n");
	printf("lang name: %s\nlang file extension: %s\nInternal interpreter\n", lang, file);
}

void print_begin(char *buf)
{
	strcat(buf, "\"");
}

void print_end(char *buf)
{
	strcat(buf, "\n\"\n");
}

void print_end_nl(char *buf)
{
	strcat(buf, "\"\n");
}

void code_begin(char *buf) {}

void code_end(char *buf) {}

void codevar(char *buf, char *p)
{
	printf("\"codevar not allowed\n\"");
}

void exec(char *file, char *buf, char *tmp)
{
	char codefile[PATH_STRING_LEN], outfile[PATH_STRING_LEN];
	int fd;
	
	char stack[BF_STACKLEN];
	char code[BF_STACKLEN];
		
	if(cache && (cacherule == CACHERULE_TIME || cacherule == CACHERULE_NOINPUT && !strcmp("", getenv("ARGS"))))
	{
		do {
			snprintf(outfile, PATH_STRING_LEN, "%s/%s.%d.%d", tmp, file, time(0), rand());
		
			fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR);
		} while(fd == -1);
		
		
		dup2(1, 3);
		close(1); dup2(fd, 1);
		do_bf(buf,strlen(buf),code,BF_STACKLEN,stack,BF_STACKLEN);
		close(fd);
		dup2(3, 1);
		
		cache_output_add(outfile,file);
		cache_print(file);
	}
	else do_bf(buf,strlen(buf),code,BF_STACKLEN,stack,BF_STACKLEN);
	
	if(cacherule)
	{
		do {
			snprintf(codefile, PATH_STRING_LEN, "%s/%s.%d.%d", tmp, file, time(0), rand());
		
			fd = open(codefile, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR);
		} while(fd == -1);
		
		write(fd, buf, strlen(buf) + 1);
		close(fd);
		cache_exec_add(codefile, file);
	}
	exit(0);
}

void cache_exec(char *path, char *tmp)
{
	char full_path[PATH_STRING_LEN];
	char outfile[PATH_STRING_LEN];
	
	char stack[BF_STACKLEN];
	char code[BF_STACKLEN];

	char *buf;
	FILE *file;
	int fd;
	int bytes;
	long filelen;
	
	bytes = snprintf(full_path, PATH_STRING_LEN, "%s/%s/%s", tmp, CACHE_DIR_EXE, path);
	if(bytes >= PATH_STRING_LEN) {
		printf("Brainfuck code file path too long\n");
		return;
	}
	file = fopen(full_path, "r");
	if(!file) {
		perror("Error opening brainfuck cache file");
		printf("Could not open brainfuck code cache file");
		return;
	}
	fseek(file, 0, SEEK_END);
	filelen = ftell(file);
	fseek(file, 0, SEEK_SET);
	buf = malloc(filelen + 1);
	fread(buf, filelen, 1, file);
	buf[filelen] = '\0';
	fclose(file);
	
	if(cache && (cacherule == CACHERULE_TIME || cacherule == CACHERULE_NOINPUT && !strcmp("", getenv("ARGS"))))
	{
		do {
			snprintf(outfile, PATH_STRING_LEN, "%s/%s.%d.%d", tmp, path, time(0), rand());
		
			fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR);
		} while(fd == -1);
		
		dup2(1, 3);
		close(1); dup2(fd, 1);
		do_bf(buf,strlen(buf),code,BF_STACKLEN,stack,BF_STACKLEN);
		close(fd);
		dup2(3, 1);
		
		cache_output_add(outfile,path);
		cache_print(path);
	}
	else do_bf(buf,strlen(buf),code,BF_STACKLEN,stack,BF_STACKLEN);
	
	free(buf);
	exit(0);
}
