#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "format.h"

unsigned int read_be32(unsigned int val)
{
	unsigned char * v = (unsigned char*) & val;
 
	return  (v[0] << 24) | (v[1] << 16) | (v[2] << 8) | v[3];
}

unsigned char* read_packet(FILE * fp, char * expect)
{
	unsigned int len;
	char head[5];
	unsigned char * rv;

	fread(&len, 4, 1, fp);
	fread(&head, 4, 1, fp);

	head[4] = 0;

	len = read_be32(len);

	fprintf(stderr, "read_packet, expect: %s\n", expect);

	if (strcmp(expect, head) != 0) {
		fprintf(stderr, "Read: %s, expect: %s\n", head, expect);
		exit(-1);
	}

	fprintf(stderr, "found: %d\n", len);

	rv = (unsigned char*) malloc(len + 8);

	memcpy(rv, &len, 4);
	memcpy(rv + 4, &head, 4);
	
	fread(rv + 8, len, 1, fp);

	return rv;
}

unsigned int * read_index_packet(FILE * fp, char * expect)
{
	unsigned int * rv = (unsigned int*) read_packet(fp, expect);
	int i;

	for (i = 2; i < rv[0]/4; i++) {
		rv[i] = read_be32(rv[i]);
	}
	return rv;
}

struct red_reob * read_reob(FILE * fp)
{
	fseek(fp, -0x38, SEEK_END);

	return (struct red_reob *) read_index_packet(fp, "REOB");
}

unsigned int * read_index(FILE * fp, unsigned int i, char * expect)
{
	fseek(fp, i, SEEK_SET);
	
	return (unsigned int*) read_index_packet(fp, expect);
}

unsigned char * read_data(FILE * fp, unsigned int i, char * expect)
{
	fseek(fp, i, SEEK_SET);
	
	return read_packet(fp, expect);
}

int main(int argc, const char** argv)
{
	FILE * fp;
	struct red_reob * reob;
        unsigned int * rdvo;
	unsigned int * rdvs;
	unsigned int * rdao;
	unsigned int * rdas;
	unsigned char * p = NULL;
	unsigned int * pl = NULL;
	unsigned int pindex;
	unsigned int offset;
	unsigned int i;

	if (argc != 4) {
		fprintf(stderr, "Usage: read_r3d fname [a|v] index\n");
		return -1;
	}

	fp = fopen(argv[1], "rb");

	if (!fp) {
		return -1;
	}

	reob = read_reob(fp);
	rdvo = read_index(fp, reob->rdvo, "RDVO");
	rdvs = read_index(fp, reob->rdvs, "RDVS");
	rdao = read_index(fp, reob->rdao, "RDAO");
	rdas = read_index(fp, reob->rdas, "RDAS");

	pindex = atoi(argv[3]);

	if (strcmp(argv[2], "a") == 0) {
		if (pindex > rdao[0]/4 || rdao[pindex+2] == 0) {
			fprintf(stderr, "EOF!\n");
			exit(-1);
		}
		p = read_data(fp, rdao[pindex+2], "REDA");
		offset = 24;
	} else if (strcmp(argv[2], "v") == 0) {
		if (pindex > rdvo[0]/4 || rdvo[pindex+2] == 0) {
			fprintf(stderr, "EOF!\n");
			exit(-1);
		}
		p = read_data(fp, rdvo[pindex+2], "REDV");
		offset = 12;
	} else {
		fprintf(stderr, "Usage: read_r3d fname [a|v] index\n");
		return -1;
	}

	if (p) {
		fwrite(p + 8 + offset, *(unsigned int*)p-8-offset, 1, stdout);
	}

	pl = ((unsigned int*)p)+2;

	fprintf(stderr, "header: ");

	for (i = 0; i < offset/4; i++) {
		fprintf(stderr, "%d ", read_be32(pl[i]));
	}
	fprintf(stderr, "\n");

	return 0;
}

