from test/more import *;

from rdf import rdf_datasets_isomorphic, rdf_iri, rdf_literal, rdf_blank, rdf_quad, RDF_NS, XSD_NS;
from rdf/parser/rdfa_core import RdfaCoreParser, CurieExpander, XHV_NS, RDFA_NS;
from rdf/parser/xhtml_rdfa import XhtmlRdfaParser;
from rdf/parser/html_rdfa import HtmlRdfaParser;

let EX := "http://example.com/";
let DC := "http://purl.org/dc/terms/";
let FOAF := "http://xmlns.com/foaf/0.1/";

// ---- CurieExpander ----

let expander := new CurieExpander();
is( expander.expand("foaf:name"), FOAF _ "name", "CurieExpander initial-context prefix" );
is( expander.expand("[dc:title]"), DC _ "title", "CurieExpander SafeCURIE" );
is( expander.expand("[]"), null, "CurieExpander empty SafeCURIE ignored" );
is(
	( new CurieExpander(base: EX) ).expand("doc"),
	EX _ "doc",
	"CurieExpander relative IRI against base",
);
is(
	expander.expand_term_or_curie_or_absiri("license"),
	XHV_NS _ "license",
	"CurieExpander initial-context term",
);
is(
	expander.expand_term_or_curie_or_absiri("nosuchterm"),
	null,
	"CurieExpander unresolvable term",
);
is(
	( expander.with_prefixes({ "ex": EX }) ).expand("ex:thing"),
	EX _ "thing",
	"CurieExpander with_prefixes",
);
is( expander.expand_curie("ex:thing"), null, "with_prefixes does not mutate original" );
is(
	( expander.with_prefixes({ "ex": EX }) ).expand("ex:column:test"),
	EX _ "column:test",
	"CurieExpander keeps colons in the reference part",
);
is( expander.expand_curie("_:blank"), null, "CurieExpander rejects the _ prefix" );
is(
	( expander.with_vocab(EX) ).expand_term_or_curie_or_absiri("license"),
	EX _ "license",
	"default vocabulary takes precedence over terms",
);

// ---- XHTML+RDFa basics ----

let xhtml := new XhtmlRdfaParser();

function _xdoc ( String body_attrs, String body ) {
	return "<html xmlns=\"http://www.w3.org/1999/xhtml\"><head><title>t</title></head>" _
		"<body" _ body_attrs _ ">" _ body _ "</body></html>";
}

// @about + @property literal
ok(
	rdf_datasets_isomorphic(
		xhtml.parse_string(
			_xdoc( "", "<p about=\"http://example.com/book\" property=\"dc:title\">Moby Dick</p>" ),
			base: EX,
		),
		[ rdf_quad( rdf_iri(EX _ "book"), rdf_iri(DC _ "title"), rdf_literal("Moby Dick") ) ],
	),
	"about + property literal",
);

// @prefix-declared CURIE
ok(
	rdf_datasets_isomorphic(
		xhtml.parse_string(
			_xdoc( "", "<p prefix=\"ex: http://example.com/ns#\" about=\"http://example.com/x\" property=\"ex:p\">v</p>" ),
			base: EX,
		),
		[ rdf_quad( rdf_iri(EX _ "x"), rdf_iri(EX _ "ns#p"), rdf_literal("v") ) ],
	),
	"prefix attribute",
);

// xmlns:-declared CURIE
ok(
	rdf_datasets_isomorphic(
		xhtml.parse_string(
			_xdoc( "", "<p xmlns:ex=\"http://example.com/ns#\" about=\"http://example.com/x\" property=\"ex:p\">v</p>" ),
			base: EX,
		),
		[ rdf_quad( rdf_iri(EX _ "x"), rdf_iri(EX _ "ns#p"), rdf_literal("v") ) ],
	),
	"xmlns prefix declaration",
);

// @vocab + rdfa:usesVocabulary
ok(
	rdf_datasets_isomorphic(
		xhtml.parse_string(
			_xdoc( "", "<p vocab=\"http://example.com/ns#\" about=\"http://example.com/x\" property=\"p\">v</p>" ),
			base: EX,
		),
		[
			rdf_quad( rdf_iri(EX _ "x"), rdf_iri(EX _ "ns#p"), rdf_literal("v") ),
			rdf_quad( rdf_iri(EX), rdf_iri(RDFA_NS _ "usesVocabulary"), rdf_iri(EX _ "ns#") ),
		],
	),
	"vocab + usesVocabulary",
);

// @content + @datatype
ok(
	rdf_datasets_isomorphic(
		xhtml.parse_string(
			_xdoc( "", "<p about=\"http://example.com/x\" property=\"dc:date\" " _
				"content=\"2026-06-10\" datatype=\"xsd:date\">today</p>" ),
			base: EX,
		),
		[ rdf_quad(
			rdf_iri(EX _ "x"),
			rdf_iri(DC _ "date"),
			rdf_literal( "2026-06-10", "", rdf_iri(XSD_NS _ "date") ),
		) ],
	),
	"content + datatype",
);

// language inheritance via xml:lang
ok(
	rdf_datasets_isomorphic(
		xhtml.parse_string(
			_xdoc( " xml:lang=\"en\"", "<p about=\"http://example.com/x\" property=\"dc:title\">Hello</p>" ),
			base: EX,
		),
		[ rdf_quad( rdf_iri(EX _ "x"), rdf_iri(DC _ "title"), rdf_literal( "Hello", "en" ) ) ],
	),
	"xml:lang inheritance",
);

// @rel + @href
ok(
	rdf_datasets_isomorphic(
		xhtml.parse_string(
			_xdoc( "", "<a about=\"http://example.com/x\" rel=\"dc:source\" href=\"http://example.com/y\">y</a>" ),
			base: EX,
		),
		[ rdf_quad( rdf_iri(EX _ "x"), rdf_iri(DC _ "source"), rdf_iri(EX _ "y") ) ],
	),
	"rel + href",
);

// xhv term in @rel
ok(
	rdf_datasets_isomorphic(
		xhtml.parse_string(
			_xdoc( "", "<a rel=\"license\" href=\"http://example.com/lic\">l</a>" ),
			base: EX,
		),
		[ rdf_quad( rdf_iri(EX), rdf_iri(XHV_NS _ "license"), rdf_iri(EX _ "lic") ) ],
	),
	"xhv rel term",
);

// @typeof on a bnode
ok(
	rdf_datasets_isomorphic(
		xhtml.parse_string(
			_xdoc( "", "<div typeof=\"foaf:Person\"><span property=\"foaf:name\">Alice</span></div>" ),
			base: EX,
		),
		[
			rdf_quad( rdf_blank("x"), rdf_iri(RDF_NS _ "type"), rdf_iri(FOAF _ "Person") ),
			rdf_quad( rdf_blank("x"), rdf_iri(FOAF _ "name"), rdf_literal("Alice") ),
		],
	),
	"typeof bnode chaining",
);

// SafeCURIE in @about
ok(
	rdf_datasets_isomorphic(
		xhtml.parse_string(
			_xdoc( "", "<p xmlns:ex=\"http://example.com/\" about=\"[ex:x]\" property=\"dc:title\">t</p>" ),
			base: EX,
		),
		[ rdf_quad( rdf_iri(EX _ "x"), rdf_iri(DC _ "title"), rdf_literal("t") ) ],
	),
	"SafeCURIE about",
);

// hanging @rel completed by child subjects
ok(
	rdf_datasets_isomorphic(
		xhtml.parse_string(
			_xdoc( "", "<div about=\"http://example.com/x\" rel=\"foaf:knows\">" _
				"<p about=\"http://example.com/y\" property=\"foaf:name\">Y</p>" _
				"</div>" ),
			base: EX,
		),
		[
			rdf_quad( rdf_iri(EX _ "x"), rdf_iri(FOAF _ "knows"), rdf_iri(EX _ "y") ),
			rdf_quad( rdf_iri(EX _ "y"), rdf_iri(FOAF _ "name"), rdf_literal("Y") ),
		],
	),
	"incomplete triple completion",
);

// @inlist
ok(
	rdf_datasets_isomorphic(
		xhtml.parse_string(
			_xdoc( "", "<div about=\"http://example.com/x\">" _
				"<span property=\"dc:creator\" inlist=\"\">A</span>" _
				"<span property=\"dc:creator\" inlist=\"\">B</span>" _
				"</div>" ),
			base: EX,
		),
		[
			rdf_quad( rdf_iri(EX _ "x"), rdf_iri(DC _ "creator"), rdf_blank("l1") ),
			rdf_quad( rdf_blank("l1"), rdf_iri(RDF_NS _ "first"), rdf_literal("A") ),
			rdf_quad( rdf_blank("l1"), rdf_iri(RDF_NS _ "rest"), rdf_blank("l2") ),
			rdf_quad( rdf_blank("l2"), rdf_iri(RDF_NS _ "first"), rdf_literal("B") ),
			rdf_quad( rdf_blank("l2"), rdf_iri(RDF_NS _ "rest"), rdf_iri(RDF_NS _ "nil") ),
		],
	),
	"inlist literal list",
);

// @role
ok(
	rdf_datasets_isomorphic(
		xhtml.parse_string(
			_xdoc( "", "<div id=\"widget\" role=\"navigation\">n</div>" ),
			base: EX,
		),
		[ rdf_quad(
			rdf_iri(EX _ "#widget"),
			rdf_iri(XHV_NS _ "role"),
			rdf_iri(XHV_NS _ "navigation"),
		) ],
	),
	"role attribute with id",
);

// ---- HTML+RDFa basics ----

let html := new HtmlRdfaParser();

ok(
	rdf_datasets_isomorphic(
		html.parse_string(
			"<!doctype html><html><body>" _
			"<p about=\"http://example.com/book\" property=\"dc:title\">Moby Dick</p>" _
			"</body></html>",
			base: EX,
		),
		[ rdf_quad( rdf_iri(EX _ "book"), rdf_iri(DC _ "title"), rdf_literal("Moby Dick") ) ],
	),
	"HTML about + property literal",
);

// <time> with @datetime
ok(
	rdf_datasets_isomorphic(
		html.parse_string(
			"<!doctype html><html><body about=\"http://example.com/x\">" _
			"<time property=\"dc:date\" datetime=\"2026-06-10\">10 June</time>" _
			"</body></html>",
			base: EX,
		),
		[ rdf_quad(
			rdf_iri(EX _ "x"),
			rdf_iri(DC _ "date"),
			rdf_literal( "2026-06-10", "", rdf_iri(XSD_NS _ "date") ),
		) ],
	),
	"HTML time datetime sniffing",
);

// <base href> sets the base
ok(
	rdf_datasets_isomorphic(
		html.parse_string(
			"<!doctype html><html><head><base href=\"http://other.example/\"></head>" _
			"<body><p about=\"doc\" property=\"dc:title\">t</p></body></html>",
			base: EX,
		),
		[ rdf_quad(
			rdf_iri("http://other.example/doc"),
			rdf_iri(DC _ "title"),
			rdf_literal("t"),
		) ],
	),
	"HTML base element",
);

// rdfa:copy property copying
ok(
	rdf_datasets_isomorphic(
		html.parse_string(
			"<!doctype html><html><body>" _
			"<div typeof=\"\"><link property=\"rdfa:copy\" href=\"#pattern\"/></div>" _
			"<div resource=\"#pattern\" typeof=\"rdfa:Pattern\">" _
			"<span property=\"dc:title\">Copied</span></div>" _
			"</body></html>",
			base: EX,
		),
		[ rdf_quad( rdf_blank("x"), rdf_iri(DC _ "title"), rdf_literal("Copied") ) ],
	),
	"rdfa:copy pattern",
);

done_testing();
