# These are mostly regression test against data obtained from the old
# FORTRAN code Helmut wrote.

import os
os.environ["GAVO_OOTTEST"] = "dontcare"

import datetime
import itertools
import functools
import pprint
import sys

from gavo.helpers import testhelpers

from gavo import api


@functools.cache
def getRD():
	return api.getRD("apfs/res/apfs_new")


class AbstractAPFSTest(testhelpers.VerboseTest):
	"""a base class for the APFS tests.

	You must override serviceId and queryParameters.  You can then
	call the makeGroundTruth class method to obtain what's supposed
	to go into groundTruth; the rest is automatic.
	"""
	groundTruth = []
	serviceId = None
	queryParameters = {}

	@classmethod
	def makeGroundTruth(cls):
		service = getRD().getById(cls.serviceId)
		res = service.run("form", cls.queryParameters, api.QueryMeta())
		pprint.pprint(res.getPrimaryTable().rows)

	def assertResultsMatch(self, coreResults, groundTruth):
		for vals_found, vals_should in itertools.zip_longest(
				coreResults, groundTruth):
			try:
				self.assertAlmostEqual(vals_found["raCio"], vals_should["raCio"])
				self.assertAlmostEqual(vals_found["raEqu"], vals_should["raEqu"])
				self.assertAlmostEqual(vals_found["dec"], vals_should["dec"])
				self.assertEqual(
					round(vals_found["arg_hour"]), vals_should["arg_hour"])
			except AssertionError:
				sys.stderr.write("For date: {}\n".format(vals_should["isodate"]))
				raise

	def testNoRegression(self):
		if self.serviceId is None:
			# we're in AbstractAPFSTest
			return

		service = getRD().getById(self.serviceId)
		res = service.run(
			"form",
			self.queryParameters,
			api.QueryMeta()).getPrimaryTable()
		self.assertResultsMatch(res.rows, self.groundTruth)

	
class FK6APFSTest(AbstractAPFSTest):
	serviceId = "catquery"
	queryParameters = {
		"object": ["902"],
		"startDate": [datetime.date(2010, 10, 10)],
		"endDate": [datetime.date(2012, 10, 20)],
		"hrInterval": [2000]}
	
	groundTruth = [{'arg_hour': 0,
  	'dec': 6.9270650787,
  	'isodate': datetime.date(2010, 10, 10),
  	'raCio': 359.8332802637,
  	'raEqu': 359.9753717276},
 	 {'arg_hour': 8,
  	'dec': 6.9264076763,
  	'isodate': datetime.date(2011, 1, 1),
  	'raCio': 359.8273367197,
  	'raEqu': 359.9727436308},
 	 {'arg_hour': 16,
  	'dec': 6.925095401,
  	'isodate': datetime.date(2011, 3, 25),
  	'raCio': 359.8230488044,
  	'raEqu': 359.9713052564},
 	 {'arg_hour': 0,
  	'dec': 6.9277713928,
  	'isodate': datetime.date(2011, 6, 17),
  	'raCio': 359.8279718202,
  	'raEqu': 359.9791255719},
 	 {'arg_hour': 8,
  	'dec': 6.9319615748,
  	'isodate': datetime.date(2011, 9, 8),
  	'raCio': 359.8334641268,
  	'raEqu': 359.9876946087},
 	 {'arg_hour': 16,
  	'dec': 6.9324998648,
  	'isodate': datetime.date(2011, 11, 30),
  	'raCio': 359.8303877982,
  	'raEqu': 359.9870906607},
 	 {'arg_hour': 0,
  	'dec': 6.9307989484,
  	'isodate': datetime.date(2012, 2, 22),
  	'raCio': 359.8237586312,
  	'raEqu': 359.9838333264},
 	 {'arg_hour': 8,
  	'dec': 6.9315693108,
  	'isodate': datetime.date(2012, 5, 15),
  	'raCio': 359.8254664542,
  	'raEqu': 359.9877178353},
 	 {'arg_hour': 16,
  	'dec': 6.9359578203,
  	'isodate': datetime.date(2012, 8, 6),
  	'raCio': 359.8322126163,
  	'raEqu': 359.9978045193}]


class OrbitTest(AbstractAPFSTest):
	# Polaris currently is the only object we have an orbit for
	queryParameters = {
				"object": ["907"],
				"startDate": [datetime.date(1995, 10, 10)],
				"endDate": [datetime.date(1996, 10, 20)],
				"hrInterval": [2000]}
	serviceId = "catquery"

	groundTruth = [{'arg_hour': 0,
  		'dec': 89.2430853934,
  		'isodate': datetime.date(1995, 10, 10),
  		'raCio': 37.395884,
  		'raEqu': 37.3434771145},
 	 	 {'arg_hour': 8,
  		'dec': 89.250626769,
  		'isodate': datetime.date(1996, 1, 1),
  		'raCio': 37.3041737726,
  		'raEqu': 37.2547217298},
 	 	 {'arg_hour': 16,
  		'dec': 89.249366217,
  		'isodate': datetime.date(1996, 3, 24),
  		'raCio': 36.8011101852,
  		'raEqu': 36.7541425787},
 	 	 {'arg_hour': 0,
  		'dec': 89.243007069,
  		'isodate': datetime.date(1996, 6, 16),
  		'raCio': 36.9263321756,
  		'raEqu': 36.8819373688},
 	 	 {'arg_hour': 8,
  		'dec': 89.2441911304,
  		'isodate': datetime.date(1996, 9, 7),
  		'raCio': 37.4899283613,
  		'raEqu': 37.4483287159}]

	def testOrbitDelta(self):
		orbit = {
			"period": 29.59,
			"ecc": 0.608,
			"tper": 1987.66,
			"node": 167.100,
			"omega": 303.010,
			"incl": 130.2,
			"axis": 21.91}
		basic_motion = {
			"raj2000": 37.95352509,
			"dej2000": 89.26410349,
			"pmra": +40.81,
			"pmdec": -15.22,
			"parallax": 7.56,
			"rv": -16.42/1000,
		}
		apfs, _ = api.loadPythonModule(getRD().getAbsPath("res/apfs"))
		# the example from src/polaris-test.f
		toEpoch = api.dateTimeToJdn(datetime.datetime(2012, 11, 2))
		dalpha, ddelta = apfs.orbitDelta(orbit, basic_motion, toEpoch)
		# this actually isn't exactly what Helmut got; he has
		# -8.1400761286797789E-005, 7.7758819818090580E-006
		# -- but since we probably won't do much orbit calculation,
		# I can't justify getting to the bottom of that.
		self.assertAlmostEqual(dalpha, -8.139655764331295e-05)
		self.assertAlmostEqual(ddelta, 7.775889202379452e-06)


class HipparcosAPFSTest(AbstractAPFSTest):
	serviceId = "hipquery"
	queryParameters = {
		"object": ["30438"],
		"startDate": [datetime.date(2010, 10, 10)],
		"endDate": [datetime.date(2012, 10, 20)],
		"hrInterval": [2000]}

	groundTruth = [{'arg_hour': 0,
  		'dec': -52.6962226824,
  		'isodate': datetime.date(2010, 10, 10),
  		'raCio': 95.9093693803,
  		'raEqu': 96.0514608442},
 	 	 {'arg_hour': 8,
  		'dec': -52.7028154913,
  		'isodate': datetime.date(2011, 1, 1),
  		'raCio': 95.915111591,
  		'raEqu': 96.0605185021},
 	 	 {'arg_hour': 16,
  		'dec': -52.707825874,
  		'isodate': datetime.date(2011, 3, 25),
  		'raCio': 95.904274953,
  		'raEqu': 96.052531405},
 	 	 {'arg_hour': 0,
  		'dec': -52.7038428288,
  		'isodate': datetime.date(2011, 6, 17),
  		'raCio': 95.8933166316,
  		'raEqu': 96.0444703833},
 	 	 {'arg_hour': 8,
  		'dec': -52.6977610637,
  		'isodate': datetime.date(2011, 9, 8),
  		'raCio': 95.8975606014,
  		'raEqu': 96.0517910833},
 	 	 {'arg_hour': 16,
  		'dec': -52.7010094202,
  		'isodate': datetime.date(2011, 11, 30),
  		'raCio': 95.9077888107,
  		'raEqu': 96.0644916732},
 	 	 {'arg_hour': 0,
  		'dec': -52.7083034544,
  		'isodate': datetime.date(2012, 2, 22),
  		'raCio': 95.9026255655,
  		'raEqu': 96.0627002607},
 	 	 {'arg_hour': 8,
  		'dec': -52.7076040366,
  		'isodate': datetime.date(2012, 5, 15),
  		'raCio': 95.8892300749,
  		'raEqu': 96.0514814559},
 	 	 {'arg_hour': 16,
  		'dec': -52.700809762,
  		'isodate': datetime.date(2012, 8, 6),
  		'raCio': 95.8871875342,
  		'raEqu': 96.0527794373}]


class GDR2APFSTest(AbstractAPFSTest):
	serviceId = "gdr2query"
	queryParameters = {
		"object": ["1737550807967929472"],
		"startDate": [datetime.date(2023, 10, 10)],
		"endDate": [datetime.date(2024, 10, 20)],
		"hrInterval": [2000]}

	groundTruth = [{'arg_hour': 0,
  	'dec': 6.8088481117,
  	'isodate': datetime.date(2023, 10, 10),
  	'raCio': 312.7191241577,
  	'raEqu': 313.0217109568},
 	 {'arg_hour': 8,
  	'dec': 6.8072838633,
  	'isodate': datetime.date(2024, 1, 1),
  	'raCio': 312.7119811469,
  	'raEqu': 313.0181109579},
 	 {'arg_hour': 16,
  	'dec': 6.8052241004,
  	'isodate': datetime.date(2024, 3, 24),
  	'raCio': 312.7133520183,
  	'raEqu': 313.0225533754},
 	 {'arg_hour': 0,
  	'dec': 6.8084112615,
  	'isodate': datetime.date(2024, 6, 16),
  	'raCio': 312.7203910464,
  	'raEqu': 313.0327663155},
 	 {'arg_hour': 8,
  	'dec': 6.8123591197,
  	'isodate': datetime.date(2024, 9, 7),
  	'raCio': 312.7208924222,
  	'raEqu': 313.0366504449}]


class GDR3APFSTest(AbstractAPFSTest):
	serviceId = "gdr3query"
	queryParameters = {
		"object": ["2062593589344878080"],
		"startDate": [datetime.date(2023, 10, 10)],
		"endDate": [datetime.date(2024, 10, 20)],
		"hrInterval": [2000]}

	groundTruth = [{'arg_hour': 0,
  		'dec': 41.1604827459,
  		'isodate': datetime.date(2023, 10, 10),
  		'raCio': 303.3801486799,
  		'raEqu': 303.6827354791},
 	 	 {'arg_hour': 8,
  		'dec': 41.1577506963,
  		'isodate': datetime.date(2024, 1, 1),
  		'raCio': 303.3703292198,
  		'raEqu': 303.6764590307},
 	 	 {'arg_hour': 16,
  		'dec': 41.1522436665,
  		'isodate': datetime.date(2024, 3, 24),
  		'raCio': 303.3727157353,
  		'raEqu': 303.6819170925},
 	 	 {'arg_hour': 0,
  		'dec': 41.1555036674,
  		'isodate': datetime.date(2024, 6, 16),
  		'raCio': 303.3811442133,
  		'raEqu': 303.6935194825},
 	 	 {'arg_hour': 8,
  		'dec': 41.1623854889,
  		'isodate': datetime.date(2024, 9, 7),
  		'raCio': 303.3792951064,
  		'raEqu': 303.6950531292}]


if __name__=="__main__":
#	GDR3APFSTest.makeGroundTruth(); sys.exit()
	testhelpers.main(OrbitTest)
