"""
The DALI sync renderer.

This is, in principle, trivial and could just go into vodal.

But then there's sufficiently many hacks in the vicinity of this that
a module of its own seems warranted.  Also, we're for now keeping
DALIRenderer here, which for now is a no-op only used for registration.
This *could* later become some sort of alias for allowed="sync,async"
defaultRenderer="info".  But let's see how the caproles discussion works out.
"""

#c Copyright 2008-2024, the GAVO project <gavo@ari.uni-heidelberg.de>
#c
#c This program is free software, covered by the GNU GPL.  See the
#c COPYING file in the source distribution.


from twisted.python import failure
from twisted.web import server

from gavo import base
from gavo import utils
from gavo.protocols import dali
from gavo.protocols import tap
from gavo.svcs import streaming
from gavo.web import grend
from gavo.web import vosi


class DALIRenderer(grend.ServiceBasedPage):
	"""A meta-renderer for DALI-like multi-renderer services (sync, async, ...)

	This, for now, can only be used for creating registry records.
	"""
	name = "dali"
	
	def render(self, request):
		raise NotImplementedError("DALI renderers do not render."
			"  I'm not joking.")

	@classmethod
	def makeAccessURL(self, basePath):
		return basePath


class SyncRenderer(grend.ServiceBasedPage):
	"""a DALI sync renderer.

	In principle, this is just a shallow parser of the input parameter
	and renders tables as VOTables.

	In practice, there are a few legacy hacks making this a bit more complicated
	after all.
	"""
	name = "sync"
	resultType = base.votableType
	urlUse = "base"
	parameterStyle = "dali"

	def render(self, request):
		# We need a bit of extra behaviour for TAP support, which isn't
		# quite DALI sync
		try:
			if self.service.core.name_=="tapCore":
				requestValue = request.strargs.get("REQUEST", [""])[0].lower()
				if requestValue=="getcapabilities":
					return vosi.VOSICapabilityRenderer(request, self.service
						).render(request)
				tap.mangleUploads(request)

			else:
				# Not TAP: use DALI standard upload mangling.
				dali.mangleUploads(request)

			self.runAsync(request.strargs
				).addCallback(self._formatOutput, request
				).addErrback(self._handleFailure, request
				).addErrback(request.finishCallback)

		except Exception:
			return self._handleFailure(failure.Failure(), request)

		return server.NOT_DONE_YET
	
	def _formatOutput(self, result, request):
		f, type = result

		def writeTable(outputFile):
			utils.cat(f, outputFile)

		request.setHeader("content-type", str(type))
		# if request has an accumulator, we're testing; this might be sync,
		# so we're shortcutting.
		if hasattr(request, "accumulator"):
			writeTable(request)
			request.finish()
		else:
			return streaming.streamOut(writeTable, request)

	def _handleFailure(self, flr, request):
		if not isinstance(flr.value, base.Error):
			base.ui.notifyFailure(flr)
		return dali.serveDALIError(request, flr.value)
