"""
A custom service that just translates IVOIDs (in the remaining url segments)
to VOResource XML.
"""

import os
import re

from gavo import base
from gavo import formal
from gavo import svcs
from gavo import utils
from gavo import web
from gavo.protocols import oaiclient
from gavo.registry.model import VOR
from gavo.utils import stanxml

oaicore, _ = utils.loadPythonModule(
	os.path.join(base.getConfig("inputsDir"), "rr", "res", "oaicore"))


class ResourceWrapper(VOR.Resource):
	"""A ri:Resource element with unparsed content.
	"""
	name_ = "Resource"
	_a_xsi_type = None

	_prefix = "ri"
	_additionalPrefixes = frozenset(["xsi"])

	def addChild(self, child):
		self._children.append(oaicore.RawXML(child))


def mungeOAIXML(oaixml):
	"""turns oaixml as generated by vorgrammar into a proper VOResource
	record.

	oaixml isn't valid XML as the namespace declarations are missing.
	Hence, we hack things a bit.
	"""
	openingElement = re.search("<ri:Resource([^>]*)>", oaixml)
	resType = re.search('xsi:type="([^"]*)"', openingElement.group(1)).group(1)
	# this doesn't *actually* parse attributes (e.g., opening and closing
	# quote mismatches are not detected), but it's good enough for plausible
	# attributes of ri:Resource
	attrPairRE = re.compile(r"\s([a-zA-Z-]+)\s*=[\"']([^\"']+)[\"']")
	nonNSAttrs = dict((m.group(1), m.group(2))
		for m in attrPairRE.finditer(openingElement.group()))

	vorxml = oaixml[
		openingElement.end():
		re.search("</ri:Resource[^>]*>", oaixml).start()]
	nsPrefixes = oaiclient.guessPrefixesUsed(vorxml)
	nsPrefixes.add(resType.split(":")[0])

	res = ResourceWrapper(xsi_type=resType)(**nonNSAttrs)[vorxml]
	oaicore._addPrefixDefs(res, nsPrefixes)
	return res


class MainPage(web.ServiceBasedPage):
	# Note: this is also used as a base class for vorlanding's MainPage.
	name = "custom"
	ivoid = None

	@classmethod
	def isBrowseable(cls, service):
		return True

	def makeResponse(self, request, oaiRec):
		"""outputs oaiRec instrumented with our stylesheet to request.

		This also makes sure our media type is text/xml so browsers
		actually apply the style sheet.
		"""
		request.setHeader("content-type", "text/xml")
		# we're managing our schema locations ourselves since we don't
		# actually parse the OAI xml.
		return (
			b"<?xml-stylesheet href='/static/xsl/oai.xsl' type='text/xsl'?>\n"
			+mungeOAIXML(oaiRec).render(includeSchemaLocation=False))

	def render_GET(self, request):
		if self.ivoid in [None, ""]:
			return web.ServiceBasedPage.render_GET(self, request)

		with base.getTableConn() as conn:
			res = list(
				conn.query("select oaixml from rr.oairecs where ivoid=%(ivoid)s",
				{"ivoid": self.ivoid}))
			if not res:
				raise svcs.UnknownURI("No resource known for %s"%self.ivoid)

		return self.makeResponse(request, res[0][0])

	def getChild(self, name, request):
		self.ivoid = "/".join(request.popSegments(name)).lower()
		if self.ivoid and not self.ivoid.startswith("ivo://"):
			self.ivoid = "ivo://"+self.ivoid
		return self

	loader = formal.XMLString(r"""
<html xmlns="xmlns=http://www.w3.org/1999/xhtml"
	xmlns:n="http://nevow.com/ns/nevow/0.1">
<head>
	<title>GAVO IVOID resolver: Pass an IVOID</title>
	<n:invisible n:render="commonhead"/>
</head>
<body style="max-width:30em">
	<h1>GAVO IVOID resolver: Pass an IVOID</h1>

	<p>This service lets you <strong>resolve</strong> IVOA identifiers, i.e., URIs
	referencing Virtual Observatory resources (they have a URI scheme
	of <tt>ivo://</tt>) to the resource records.  There you will find all kinds
	of metadata there, including access options (“capabilities”).</p>

	<p><strong>To do this</strong> resolution, take an IVOID and prepend
	it with <tt>https://dc.g-vo.org/I/</tt>.</p>

	<p><strong>For instance</strong>, to this service is registered as
	<tt>ivo://org.gavo.dc/rr/q/nmah</tt>.  To see the registry record,
	you would paste
	<a href="https://dc.g-vo.org/I/ivo://org.gavo.dc/rr/q/nmah"
		>https://dc.g-vo.org/I/ivo://org.gavo.dc/rr/q/nmah</a>
	into your web browser's address line.</p>

	<p><a href="/rr/q/nmah/info">More on this service</a>.</p>
</body>
</html>""")

