#ifdef ORCAD_TESTER
#	include "tester/read_fio.h"
#else
#	include "read_fio.h"
#endif
#include "read_common.h"
#include <stdio.h>
#include <string.h>
#include <time.h>

long orcad_dump_symbolpin(io_orcad_rctx_t* const rctx, long offs, int indent)
{
	struct orcad_header hdr;
	char buf[256];
	my_int32_t start_x, start_y;
	my_int32_t hotpt_x, hotpt_y;
	my_uint16_t pin_shape;
	my_uint32_t port_type;
	my_uint16_t cnt;

	if(0>(offs=orcad_parse_header(rctx, offs, &hdr)))
	{
		fprintf(stderr, "Error: Could not parse symbolpin object header\n");
		return -1;
	}

	orcad_check_hdr_type(hdr, ORCAD_TYPE_SYMBOLPIN);

	indent_printf("begin symbolpin\n");
	++indent;

	if(0>(offs=orcad_read_string2(rctx, offs, buf, sizeof(buf))))
	{
		fprintf(stderr, "Error: Could not read lib path\n");
		return -1;
	}

	indent_printf("pin_name: \"%s\"\n", buf);
	read_int32(start_x);
	read_int32(start_y);
	read_int32(hotpt_x);
	read_int32(hotpt_y);
	read_uint16(pin_shape);
	dump_hex16("unk[0]");
	read_uint32(port_type);
	dump_hex16("unk[1]");
	dump_hex16("unk[2]");

	if(0>(offs=orcad_read_field_16(rctx, offs, &cnt)))
	{
		fprintf(stderr, "Error: Could not read symboldisplayprop count\n");
		return -1;
	}

	indent_printf("num_symboldisplayprops: %u\n", (unsigned int)cnt);

	while(0<(cnt--))
	{
		if(0>(offs=orcad_skip_object(rctx, offs, indent+1)))
		{
			fprintf(stderr, "Error: Could not dump symboldisplayprop\n");
			return -1;
		}
	}

	--indent;
	indent_printf("end symbolpin\n");

	return offs;
}

long orcad_dump_pinidxmapping(io_orcad_rctx_t* const rctx, long offs, int indent)
{
	struct orcad_header hdr;
	char buf[256];
	my_uint16_t pin;
	my_uint16_t cnt;

	if(0>(offs=orcad_parse_header(rctx, offs, &hdr)))
	{
		fprintf(stderr, "Error: Could not parse pinidxmapping object header\n");
		return -1;
	}

	orcad_check_hdr_type(hdr, ORCAD_TYPE_PINIDXMAPPING);

	indent_printf("begin pinidxmapping\n");
	++indent;

	if(0>(offs=orcad_read_string2(rctx, offs, buf, sizeof(buf))))
	{
		fprintf(stderr, "Error: Could not read lib path\n");
		return -1;
	}

	indent_printf("unit_ref: \"%s\"\n", buf);

	if(0>(offs=orcad_read_string2(rctx, offs, buf, sizeof(buf))))
	{
		fprintf(stderr, "Error: Could not read lib path\n");
		return -1;
	}

	indent_printf("symname: \"%s\"\n", buf);

	if(0>(offs=orcad_read_field_16(rctx, offs, &cnt)))
	{
		fprintf(stderr, "Error: Could not read pin count\n");
		return -1;
	}

	indent_printf("num_pins: %u\n", (unsigned int)cnt);

	for(pin=1;pin<=cnt;++pin)
	{
		my_uint16_t len;

		indent_printf("begin pin_%u\n", (unsigned int)pin);
		++indent;

		if(0>(offs=orcad_read_field_16(rctx, offs, &len)))
		{
			fprintf(stderr, "Error: Could not read pin string length\n");
			return -1;
		}

		if(0xFFFF==len)
		{
			indent_printf("empty/missing pin\n");
		}
		else
		{
			my_uint8_t pincfg;

			if(0>(offs=orcad_read_string(rctx, offs, buf, sizeof(buf), len)))
			{
				fprintf(stderr, "Error: Could not read pin name\n");
				return -1;
			}

			indent_printf("pin_name: \"%s\"\n", buf);

			if(1!=fio_fread(rctx, (char*)&pincfg, 1))
			{
				fprintf(stderr, "Error: Could not read pincfg\n");
				return -1;
			}

			++offs;

			indent_printf("pin_ignore: %i\n", !!(0x80 & pincfg));
			pincfg &= 0x7f;

			if(0x7f!=pincfg)
			{
				indent_printf("pin_group: %u\n", (unsigned int)pincfg);
			}
			else
			{
				indent_printf("pin_group: empty\n");
			}
		}

		--indent;
		indent_printf("end pin_%u\n", (unsigned int)pin);
	}

	--indent;
	indent_printf("end pinidxmapping\n");

	return offs;
}

long orcad_cache_dump_variant(io_orcad_rctx_t* const rctx, long offs,
	int indent)
{
	char buf[256];
	my_uint8_t type[2];
	my_uint16_t cnt;
	struct orcad_header hdr;
	long end;

	if(0>(offs=orcad_read_string2(rctx, offs, buf, sizeof(buf))))
	{
		fprintf(stderr, "Error: Could not read lib path\n");
		return -1;
	}

	indent_printf("lib_path: \"%s\"\n", buf);
	dump_time32("ctime");
	dump_time32("mtime");

	fio_fread(rctx, (char*)&type[0], sizeof(type));
	offs += sizeof(type);
	indent_printf("type: 0x%x, 0x%x\n", (unsigned int)type[0],
		(unsigned int)type[1]);

	if(0>(offs=orcad_parse_header(rctx, offs, &hdr)))
	{
		fprintf(stderr, "Error: Could not read sym header\n");
		return -1;
	}

	end = offs + hdr.size;

	if(0>(offs=orcad_read_string2(rctx, offs, buf, sizeof(buf))))
	{
		fprintf(stderr, "Error: Could not read sym name\n");
		return -1;
	}

	indent_printf("name: \"%s\"\n", buf);

	if(0>(offs=orcad_read_string2(rctx, offs, buf, sizeof(buf))))
	{
		fprintf(stderr, "Error: Could not read sym source path\n");
		return -1;
	}

	indent_printf("source: \"%s\"\n", buf);

	if(0x1f==type[0])
	{
		if(0>(offs=orcad_read_string2(rctx, offs, buf, sizeof(buf))))
		{
			fprintf(stderr, "Error: Could not read sym source path\n");
			return -1;
		}

		indent_printf("sym_prefix: \"%s\"\n", buf);

		if(0>(offs=orcad_skip_field_16(rctx, offs, 0x0000)))
		{
			fprintf(stderr, "Error: Failed to skip\n");
			return -1;
		}

		if(0>(offs=orcad_skip_field_16(rctx, offs, 0x0000)))
		{
			fprintf(stderr, "Error: Failed to skip\n");
			return -1;
		}

		if(0>(offs=orcad_skip_field_16(rctx, offs, 0x0000)))
		{
			fprintf(stderr, "Error: Failed to skip\n");
			return -1;
		}

		if(0>(offs=orcad_read_field_16(rctx, offs, &cnt)))
		{
			fprintf(stderr, "Error: Could not read pin-index mapping count\n");
			return -1;
		}

		indent_printf("num_pinidxmapping: %u\n", (unsigned int)cnt);

		while(0<(cnt--))
		{
			if(0>(offs=orcad_dump_pinidxmapping(rctx, offs, indent+1)))
			{
				fprintf(stderr, "Error: Could not dump pinidxmapping\n");
				return -1;
			}
		}

		/* this type ends here */
	}
	else
	if(0x40==type[0])
	{
		dump_hex16("unk[0]");
		dump_hex16("unk[1]");

		if(0>(offs=orcad_read_field_16(rctx, offs, &cnt)))
		{
			fprintf(stderr, "Error: Could not read primitive count\n");
			return -1;
		}

		indent_printf("num_primitives: %u\n", (unsigned int)cnt);

		while(0<(cnt--))
		{
/*			if(0>(offs=orcad_read_primitive(rctx, offs, indent+1)))*/
			{
				/*orcad_error_backtrace__(&node->node, "read primitives");*/
				fprintf(stderr, "Error: Could not dump primitives\n");
				return -1;
			}
		}

		if(0>(offs=orcad_skip_field_32(rctx, offs, 0x00000000)))
		{
			fprintf(stderr, "Error: Could not skip zero field\n");
			return -1;
		}

		dump_hex16("unk[2]");
		dump_hex16("unk[3]");
		dump_hex16("unk[4]");

		if(0>(offs=orcad_read_field_16(rctx, offs, &cnt)))
		{
			fprintf(stderr, "Error: Could not read symboldisplayprop count\n");
			return -1;
		}

		indent_printf("num_symboldisplayprops: %u\n", (unsigned int)cnt);

		while(0<(cnt--))
		{
			if(0>(offs=orcad_skip_object(rctx, offs, indent+1)))
			{
				fprintf(stderr, "Error: Could not dump symboldisplayprop\n");
				return -1;
			}
		}

		/* this type ends here */
	}
	else
	if(0x18==type[0])
	{
		my_uint16_t symtypename_x;
		my_uint16_t symtypename_y;

		dump_hex16("unk[0]");
		dump_hex16("unk[1]");

		if(0>(offs=orcad_read_field_16(rctx, offs, &cnt)))
		{
			fprintf(stderr, "Error: Could not read primitive count\n");
			return -1;
		}

		indent_printf("num_primitives: %u\n", (unsigned int)cnt);

		while(0<(cnt--))
		{
/*			if(0>(offs=orcad_read_primitive(rctx, offs, indent+1)))*/
			{
				/*orcad_error_backtrace__(&node->node, "read primitives");*/
				fprintf(stderr, "Error: Could not dump primitives\n");
				return -1;
			}
		}

		if(0>(offs=orcad_skip_field_32(rctx, offs, 0x00000000)))
		{
			fprintf(stderr, "Error: Could not skip zero field\n");
			return -1;
		}

		read_uint16(symtypename_x);
		read_uint16(symtypename_y);

		if(0>(offs=orcad_read_field_16(rctx, offs, &cnt)))
		{
			fprintf(stderr, "Error: Could not read symbolpin count\n");
			return -1;
		}

		indent_printf("num_symbolpins: %u\n", (unsigned int)cnt);

		while(0<(cnt--))
		{
			if(0>(offs=orcad_dump_symbolpin(rctx, offs, indent+1)))
			{
				fprintf(stderr, "Error: Could not dump symbolpin\n");
				return -1;
			}
		}

		if(0>(offs=orcad_read_field_16(rctx, offs, &cnt)))
		{
			fprintf(stderr, "Error: Could not read symboldisplayprop count\n");
			return -1;
		}

		indent_printf("num_symboldisplayprops: %u\n", (unsigned int)cnt);

		while(0<(cnt--))
		{
			if(0>(offs=orcad_skip_object(rctx, offs, indent+1)))
			{
				fprintf(stderr, "Error: Could not dump symboldisplayprop\n");
				return -1;
			}
		}

		dump_hex16("unk[2]");
		dump_hex16("unk[3]");
		dump_hex16("unk[4]");

		if(0>(offs=orcad_read_string2(rctx, offs, buf, sizeof(buf))))
		{
			fprintf(stderr, "Error: Could not read sym source path\n");
			return -1;
		}

		indent_printf("sym_prefix: \"%s\"\n", buf);

		dump_hex8("unk[5]");
		dump_hex16("unk[6]");
		dump_hex16("unk[7]");

		/* this type ends here */
	}
	else
	if(0x6==type[0])
	{
		if(0>(offs=orcad_read_field_16(rctx, offs, &cnt)))
		{
			fprintf(stderr, "Error: Could not read name count\n");
			return -1;
		}

		indent_printf("num_part_names: %u\n", (unsigned int)cnt);

		while(0<(cnt--))
		{
			if(0>(offs=orcad_read_string2(rctx, offs, buf, sizeof(buf))))
			{
				fprintf(stderr, "Error: Could not read part name\n");
				return -1;
			}

			indent_printf("part_name: \"%s\"\n", buf);
		}

		/* this type ends here */
	}
	else
	if(0x21==type[0])
	{
		my_uint16_t symtypename_x;
		my_uint16_t symtypename_y;

		dump_hex16("unk[0]");
		dump_hex16("unk[1]");

		if(0>(offs=orcad_read_field_16(rctx, offs, &cnt)))
		{
			fprintf(stderr, "Error: Could not read primitive count\n");
			return -1;
		}

		indent_printf("num_primitives: %u\n", (unsigned int)cnt);

		while(0<(cnt--))
		{
/*			if(0>(offs=orcad_read_primitive(rctx, offs, indent+1)))*/
			{
				/*orcad_error_backtrace__(&node->node, "read primitives");*/
				fprintf(stderr, "Error: Could not dump primitives\n");
				return -1;
			}
		}

		if(0>(offs=orcad_skip_field_32(rctx, offs, 0x00000000)))
		{
			fprintf(stderr, "Error: Could not skip zero field\n");
			return -1;
		}

		read_uint16(symtypename_x);
		read_uint16(symtypename_y);

		if(0>(offs=orcad_read_field_16(rctx, offs, &cnt)))
		{
			fprintf(stderr, "Error: Could not read symbolpin count\n");
			return -1;
		}

		indent_printf("num_symbolpins: %u\n", (unsigned int)cnt);

		while(0<(cnt--))
		{
			if(0>(offs=orcad_dump_symbolpin(rctx, offs, indent+1)))
			{
				fprintf(stderr, "Error: Could not dump symbolpin\n");
				return -1;
			}
		}

		if(0>(offs=orcad_read_field_16(rctx, offs, &cnt)))
		{
			fprintf(stderr, "Error: Could not read symboldisplayprop count\n");
			return -1;
		}

		indent_printf("num_symboldisplayprops: %u\n", (unsigned int)cnt);

		while(0<(cnt--))
		{
			if(0>(offs=orcad_skip_object(rctx, offs, indent+1)))
			{
				fprintf(stderr, "Error: Could not dump symboldisplayprop\n");
				return -1;
			}
		}

		/* this type ends here */
	}
	else
	{
		fprintf(stderr, "Error: Unhandled type in cache: 0x%x (offs: 0x%lx)\n",
			(unsigned int)type[0], offs);
		return -1;
	}

	if(offs!=end)
	{
		fprintf(stderr, "Error: Structure overread or unparsed segments "
			"remained! offs=0x%lx, end=0x%lx\n", offs, end);
		return -1;
	}

	return offs;
}

long orcad_cache_dump_symbol(io_orcad_rctx_t* const rctx, long offs,
	int indent)
{
	my_uint16_t cnt;
	char buf[256];

	indent_printf("begin symbol\n");
	++indent;

	if(0>(offs=orcad_read_string2(rctx, offs, buf, sizeof(buf))))
	{
		fprintf(stderr, "Error: Could not read symname\n");
		return -1;
	}

	indent_printf("symname: \"%s\"\n", buf);

	if(0>(offs=orcad_read_field_16(rctx, offs, &cnt)))
	{
		fprintf(stderr, "Error: Could not read symbol variant count\n");
		return -1;
	}

	indent_printf("num_variants: %u\n", (unsigned int)cnt);

	while(0<(cnt--))
	{
		if(0>(offs=orcad_cache_dump_variant(rctx, offs, indent+1)))
		{
			fprintf(stderr, "Error: Could not dump variant\n");
			return -1;
		}
	}

	--indent;
	indent_printf("end symbol\n");

	return offs;
}

long orcad_cache_dump_symbolgroup(io_orcad_rctx_t* const rctx, long offs,
	int indent)
{
	my_uint16_t cnt;

	indent_printf("begin symbolgroup\n");
	++indent;

	if(0>(offs=orcad_read_field_16(rctx, offs, &cnt)))
	{
		fprintf(stderr, "Error: Could not read symbol count\n");
		return -1;
	}

	indent_printf("num_syms: %u\n", (unsigned int)cnt);

	while(0<(cnt--))
	{
		if(0>(offs=orcad_cache_dump_symbol(rctx, offs, indent+1)))
		{
			fprintf(stderr, "Error: Could not dump symbol\n");
			return -1;
		}
	}

	--indent;
	indent_printf("end symbolgroup\n");

	return offs;
}

int orcad_dump_cache(io_orcad_rctx_t* const rctx)
{
	long offs;
	int indent;
	char tmp;

	offs = 0;
	indent = 0;

	if(0>(offs=orcad_skip_field_16(rctx, offs, 0x0000)))
	{
		fprintf(stderr, "Error: First 16-bit field is not 0x0000!\n");
		return -1;
	}

	while(sizeof(tmp)==fio_fread(rctx, &tmp, sizeof(tmp)))
	{
		/* no peek function, seek back! */
		fio_fseek(rctx, offs);

		if(0>(offs=orcad_cache_dump_symbolgroup(rctx, offs, indent)))
		{
			fprintf(stderr, "Error: Could not dump symbolgroup\n");
			return -1;
		}
	}

	return 0;
}
