#include <string.h>

#include <kalmia.h>
#include "geometry.h"
#include "test/test.h"


LILY_FILE_BEGIN(geometry_suite)


LILY_TEST("fail to read non-float_array")
{
	struct kai_tag_t *t = kai_parse_string(
		"<non_float_array></non_float_array>"
	);

	struct ka_float_array_t arr;
	int result = kai_read_float_array(&arr, t);
	CHECK_EQ(result, -1, "%d");

	kai_tag_destroy(t);
}
#include LILY_PUSH_TEST()


LILY_TEST("fail to read float_array without count attribute")
{
	struct kai_tag_t *t = kai_parse_string(
		"<float_array id=\"some id\">"
		"	blah blah internals"
		"</float_array>"
	);

	struct ka_float_array_t arr;
	int result = kai_read_float_array(&arr, t);
	CHECK_EQ(result, -1, "%d");

	kai_tag_destroy(t);
}
#include LILY_PUSH_TEST()


LILY_TEST("read normal float_array")
{
	struct kai_tag_t *t = kai_parse_string(
		"<float_array count=\"3\" id=\"arr\">"
		"	-0.5 0.0 0.5"
		"</float_array>"
	);

	struct ka_float_array_t arr;
	int result = kai_read_float_array(&arr, t);
	REQUIRE_EQ(result, 0, "%d");
	kai_tag_destroy(t);

	REQUIRE_EQ(arr.count, 3, "%d");
	CHECK_EQS(arr.id, "arr");
	CHECK_EQ(arr.digits, 6, "%d");
	CHECK_EQ(arr.magnitude, 38, "%d");

	CHECK_EQF(arr.buf[0], -0.5, "%f");
	CHECK_EQF(arr.buf[1],  0.0, "%f");
	CHECK_EQF(arr.buf[2],  0.5, "%f");

	kai_release_float_array(arr);
}
#include LILY_PUSH_TEST()


LILY_TEST("fail to read non-param tag")
{
	struct kai_tag_t *t = kai_parse_string(
		"<tag />"
	);

	struct ka_param_t param;
	int result = kai_read_param(&param, t);
	CHECK_EQ(result, -1, "%d");

	kai_tag_destroy(t);
}
#include LILY_PUSH_TEST()


LILY_TEST("fail to read param tag with no specified type")
{
	struct kai_tag_t *t = kai_parse_string(
		"<param />"
	);

	struct ka_param_t param;
	int result = kai_read_param(&param, t);
	CHECK_EQ(result, -1, "%d");

	kai_tag_destroy(t);
}
#include LILY_PUSH_TEST()


LILY_TEST("read param tag")
{
	struct kai_tag_t *t = kai_parse_string(
		"<param type=\"float\" name=\"x\" />"
	);

	struct ka_param_t param;
	int result = kai_read_param(&param, t);
	kai_tag_destroy(t);

	REQUIRE_EQ(result, 0, "%d");
	CHECK_EQS(param.name, "x");
	CHECK_EQ(param.sid, NULL, "%p");
	CHECK_EQS(param.type, "float");
	CHECK_EQ(param.semantic, NULL, "%p");

	kai_release_param(param);
}
#include LILY_PUSH_TEST()


LILY_TEST("fail to read non-accessor tag")
{
	struct kai_tag_t *t = kai_parse_string(
		"<tag />"
	);

	struct ka_accessor_t accessor;
	int result = kai_read_accessor(&accessor, t);
	CHECK_EQ(result, -1, "%d");

	kai_tag_destroy(t);
}
#include LILY_PUSH_TEST()


LILY_TEST("fail to read accessor tag with no specified count or source")
{
	struct kai_tag_t *t = kai_parse_string(
		"<accessor />"
	);

	struct ka_accessor_t accessor;
	int result = kai_read_accessor(&accessor, t);
	CHECK_EQ(result, -1, "%d");

	kai_tag_destroy(t);
}
#include LILY_PUSH_TEST()


LILY_TEST("parse accessor")
{
	struct kai_tag_t *t = kai_parse_string(
		"<accessor source=\"some id\" count=\"6\" stride=\"3\">"
		"	<param type=\"float\" name=\"x\" />"
		"	<param type=\"float\" name=\"y\" />"
		"	<param type=\"float\" name=\"z\" />"
		"</accessor>"
	);

	struct ka_accessor_t acc;
	int result = kai_read_accessor(&acc, t);
	kai_tag_destroy(t);

	CHECK_EQ(result, 0, "%d");
	CHECK_EQ(acc.count, 6, "%d");
	CHECK_EQ(acc.offset, 0, "%d");
	CHECK_EQS(acc.source, "some id");
	CHECK_EQ(acc.stride, 3, "%d");

	REQUIRE_EQ(acc.param_count, 3, "%d");
	CHECK_EQS(acc.param[0].name, "x");
	CHECK_EQS(acc.param[1].name, "y");
	CHECK_EQS(acc.param[2].name, "z");

	kai_release_accessor(acc);
}
#include LILY_PUSH_TEST()


LILY_TEST("fail to read non-source tag")
{
	struct kai_tag_t *t = kai_parse_string(
		"<tag />"
	);

	struct ka_source_t source;
	int result = kai_read_source(&source, t);
	CHECK_EQ(result, -1, "%d");

	kai_tag_destroy(t);
}
#include LILY_PUSH_TEST()


LILY_TEST("fail to read source tag with no specified id")
{
	struct kai_tag_t *t = kai_parse_string(
		"<source />"
	);

	struct ka_source_t source;
	int result = kai_read_source(&source, t);
	CHECK_EQ(result, -1, "%d");

	kai_tag_destroy(t);
}
#include LILY_PUSH_TEST()


LILY_TEST("read source correctly")
{
	struct kai_tag_t *t = kai_parse_string(
		"<source id=\"source\">"
		"	<float_array count=\"1\">0.0</float_array>"
		"	<technique_common>"
		"		<accessor count=\"1\" source=\"xxx\">"
		"			<param type=\"float\" />"
		"		</accessor>"
		"	</technique_common>"
		"</source>"
	);

	struct ka_source_t source;
	int result = kai_read_source(&source, t);
	kai_tag_destroy(t);

	CHECK_EQ(result, 0, "%d");
	REQUIRE_EQS(source.id, "source");
	CHECK_EQS(source.name, NULL);

	CHECK_EQ(source.float_array.count, 1, "%d");
	CHECK_EQS(source.accessor.source, "xxx");

	kai_release_source(source);
}
#include LILY_PUSH_TEST()


#define LILY_FILE_END
#include LILY_REGISTER_TESTS()