// intellectual property is bullshit bgdc

#include "ascii85.h"
#include "base64.h"

#include <stdbool.h>
#include <stddef.h>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>

static void usage(char const * argv0)
{
	fprintf(stderr, "%s 85enc|85dec|64enc|64dec [IN [OUT]]\n", argv0);
}

int main(int argc, char ** argv)
{
	bool decode = false;
	bool base64 = false;

	if (argc < 2)
	{
		usage(argv[0]);
		return 1;
	}

	if (!strcmp(argv[1], "85enc"))
	{
		decode = false;
		base64 = false;
	}
	else if (!strcmp(argv[1], "85dec"))
	{
		decode = true;
		base64 = false;
	}
	else if (!strcmp(argv[1], "64enc"))
	{
		decode = false;
		base64 = true;
	}
	else if (!strcmp(argv[1], "64dec"))
	{
		decode = true;
		base64 = true;
	}
	else
	{
		usage(argv[0]);
		return 1;
	}

	FILE * f_in = NULL, * f_out = NULL;

	if (argc < 3)
		f_in = stdin;
	else if (!strcmp(argv[2], "-"))
		f_in = stdin;
	else
	{
		f_in = fopen(argv[2], "r");
		if (!f_in)
		{
			perror("fopen");
			return 1;
		}
	}

	if (argc < 4)
		f_out = stdout;
	else if (!strcmp(argv[3], "-"))
		f_out = stdout;
	else
	{
		f_out = fopen(argv[3], "w");
		if (!f_out)
		{
			perror("fopen");
			return 1;
		}
	}

	size_t n_raw, n_encoded;

	if (base64)
	{
		n_raw = 513;
		n_encoded = 684;
	}
	else
	{
		n_raw = 512;
		n_encoded = 640;
	}

	uint8_t in_buffer[decode ? n_encoded : n_raw];
	uint8_t out_buffer[decode ? n_raw : n_encoded];

	while (!ferror(f_in) && !feof(f_in) && !ferror(f_out) && !feof(f_out))
	{
		size_t n = fread(in_buffer, 1, sizeof(in_buffer), f_in);
		size_t n_converted;

		if (decode && base64)
			n_converted = base64_decode(out_buffer, in_buffer, n);
		else if (!decode && base64)
			n_converted = base64_encode(out_buffer, in_buffer, n);
		else if (decode && !base64)
			n_converted = ascii85_encode(out_buffer, in_buffer, n);
		else
			n_converted = ascii85_decode(out_buffer, in_buffer, n);

		fwrite(out_buffer, 1, n_converted, f_out);
	}

	fclose(f_in);
	fclose(f_out);
	return 0;
}
