"""
Tests for our datapack outputs.
"""

#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 gavo.helpers import testhelpers

import os
import shutil

from gavo import api
from gavo.protocols import datapack

class _DataPackageDescriptor(testhelpers.TestResource):
	def make(self, ignored):
		rd = datapack.getRDForDump("data/cores")
		res = datapack.makeDescriptor(rd)
		return res


class DataPackageDescriptorTest(testhelpers.VerboseTest):
	resources = [
		("desc", _DataPackageDescriptor())]

	def testTitleInferred(self):
		self.assertEqual(self.desc["name"], "test")
	
	def testDaCHSIndicator(self):
		self.assertEqual(self.desc["dachs-resdir"], "")
	
	def testDOI(self):
		self.assertEqual(self.desc["id"], "10.5072/test-fixture")
	
	def testLicense(self):
		self.assertEqual(len(self.desc["licenses"]), 1)
		self.assertEqual(self.desc["licenses"][0]["path"],
			"https://spdx.org/licenses/CC0-1.0.html")

	def testTitle(self):
		self.assertEqual(self.desc["title"], "Test Fixtures")
	
	def testDescription(self):
		self.assertEqual(self.desc["description"], "Helpers for tests for cores.")
	
	def testHomepage(self):
		self.assertEqual(self.desc["homepage"],
			"http://localhost:8080/browse/data/cores")

	def testVersion(self):
		self.assertEqual(self.desc["version"], "2.3.1pl2+git_deadbeef")

	def testContributors(self):
		self.assertEqual(self.desc["contributors"], [
			{'role': 'author', 'title': 'Gandalf, W.'},
			{'role': 'author', 'title': 'Baggins, B.'},
			{'role': 'author', 'title': 'Baggins, F.'}])

	def testCreated(self):
		self.assertEqual(self.desc["created"], "2010-12-01T14:00:00Z")

	def testMinimal(self):
		rd = api.parseFromString(api.RD, '<resource schema="nirvana"/>')
		rd.filesLoaded = []
		rd.sourceId = "nirvana/bar"
		rd.srcPath = rd.resdir
		res = datapack.makeDescriptor(rd)
		res.pop("resources")
		self.assertEqual(res, {
			"name": "nirvana", "dachs-resdir": "nirvana",
			"profile": "data-package",
			'homepage': 'http://localhost:8080/browse/nirvana/bar'})


class _DataPackageTestMixin:
	def _expectFile(self, path, assertName=None):
		for r in self.dpRscs:
			if r["path"]==path:
				if assertName is not None:
					self.assertEqual(r["name"], assertName)
				break
		else:
			raise AssertionError("%s not found in returned resources"%path)

	def _expectNoFile(self, name):
		for r in self.dpRscs:
			if r["path"]==name:
				raise AssertionError("%s is found in returned resources"
					" although it should not be there."%name)


class _DataPackageResources(testhelpers.TestResource):
	def make(self, ignored):
		with testhelpers.messageCollector() as msg:
			res = list(datapack.iterRDResources(
				datapack.getRDForDump("data/test")))
		res.append({
			"name": "fake-warning-messages",
			"path": "None",
			"messages": msg})
		return res


class DataPackageResourcesTest(
		testhelpers.VerboseTest,
		_DataPackageTestMixin):
	resources = [("dpRscs", _DataPackageResources())]

	def testRDPresent(self):
		self.assertEqual(self.dpRscs[0]["path"], "data/test.rd")

	def testDirectSource(self):
		self._expectFile('data/adqlin.txt')

	def testFITS(self):
		self._expectFile('data/ex.fits')

	def testSpectrum(self):
		self._expectFile('data/a.imp')

	def testUniqueNames(self):
		self.assertEqual(
			len(set(r["name"] for r in self.dpRscs)),
			len(self.dpRscs))
	
	def testMessage(self):
		type, args, _ = self.dpRscs[-1]["messages"].events[0]
		self.assertEqual(type, "Warning")
		self.assertEqual(args[0],
			"data data/test#productimport ignored because of dynamic ignoreSources")


class _ResourceCollectingResdir(testhelpers.TestResource):
	def make(self, ignored):
		self.respath = os.path.join(api.getConfig("inputsDir"), "dpexp")
		os.makedirs(self.respath, exist_ok=True)

		def w(n, content):
			with open(os.path.join(self.respath, n), "w", encoding="utf-8") as f:
				f.write(content)

		w("q.rd", """<resource schema="dpexp">
			<property name="datapack-extrafiles"
				>["subdir/*.knack", "worn", "gibtsnicht"]</property>
			<table id="main" onDisk="True"/>
			<data>
				<sources pattern="data/*.txt"/>
				<directGrammar cBooster="res/booster.c"/>
				<make table="main"/>
			</data>
			<service customPage="cp">
				<template key="fixed">template.html</template>
				<customCore module="cm"/>
			</service>
			</resource>
		""")
		
		w("cm.py", "from gavo import api\nclass Core(api.Core): pass\n")
		w("template.html", "<html/>")
		w("cp.py", "MainPage = None")

		os.makedirs(self.respath+"/res", exist_ok=True)
		for n in ["worn",  "res/booster.c", "README"]:
			w(n, "")

		os.makedirs(self.respath+"/subdir", exist_ok=True)
		for n in ["subdir/nix", "subdir/a.knack", "subdir/b.knack"]:
			w(n, "")

		return "dpexp/q"

	def clean(self, ignored):
		shutil.rmtree(self.respath)

_resourceCollectingResdir = _ResourceCollectingResdir()


class _CollectedResources(testhelpers.TestResource):
	resources = [("rdid", _resourceCollectingResdir)]

	def make(self, deps):
		rd = datapack.getRDForDump(deps["rdid"])
		return list(datapack.iterRDResources(rd))


class DataPackageExtraResourcesTest(
		testhelpers.VerboseTest,
		_DataPackageTestMixin):
	resources = [("dpRscs", _CollectedResources())]

	def testRD(self):
		self.assertEqual(self.dpRscs[0]["path"], "q.rd")
		self.assertEqual(self.dpRscs[0]["name"], "dachs-resource-descriptor")
		self.assertEqual(self.dpRscs[0]["mediatype"], "text/xml")

	def testREADME(self):
		self._expectFile("README", "readme")

	def testManualWildcard(self):
		self._expectFile("subdir/a.knack")
		self._expectFile("subdir/b.knack")

	def testManualLiteral(self):
		self._expectFile("worn")
	
	def testManualNoOverinclusion(self):
		self._expectNoFile("subdir/nix")
	
	def testManualNoMissingFiles(self):
		self._expectNoFile("gibtsnicht")

	def testBoosterIncluded(self):
		self._expectFile("res/booster.c")
	
	def testCustomPageIncluded(self):
		self._expectFile("cp.py")

	def testTemplateIncluded(self):
		self._expectFile("template.html")

	def testCustomCoreIncluded(self):
		self._expectFile("cm.py")


if __name__=="__main__":
	testhelpers.main(DataPackageExtraResourcesTest)
