# -*- coding: utf-8 -*-
"""
Make an expression for res/jsogrammar to parse a file of a certain type.

Pass a sample file to this program.

See also README.
"""

import code
import os
import re
import sys
import warnings
import zipfile
from cStringIO import StringIO

from gavo import api
sys.path.append(api.getRD("c8spect/q").resdir+"/res")
import javaobj


def getFieldSequenceForInstance(instance, attPath):
	if instance is None:
		warnings.warn("NULL value %s -- ignoring this path."%(attPath))
		return []

	cls = instance.get_class()
	fieldSequence = []
	while cls:
		for name, type in zip(cls.fields_names, cls.fields_types):
			if len(type)==1:  # atomic type
				fieldSequence.append((name, attPath+"."+name, type))

			elif type=='Ljava/lang/String;':
				fieldSequence.append((name, attPath+"."+name, type))

			elif type.startswith('['):
				# an array
				fieldSequence.append((name,
					"numpy.array(%s)"%(attPath+"."+name), type))

			else:
				# a complex object, recurse
				fieldSequence.append((None, None, ">"))
				fieldSequence.extend(getFieldSequenceForInstance(
					getattr(instance, name), attPath+"."+name))
				fieldSequence.append((None, None, "<"))
		cls = cls.superclass
	return fieldSequence


def getDecodedDataFromGbin(sourceName):
	f = open(sourceName)
	f.seek(0x1b)  # skip outer JSO armor
	zf = zipfile.ZipFile(file=f)
	names = zf.namelist()
	assert len(names)==1
	data = zf.open(names[0]).read()
	return javaobj.loads(data)


def makePythonExpression(fieldSequence, ignored):
	buf = []
	for name, path, type in fieldSequence:
		if name is None:
			continue
		buf.append("\t\t\t\t# %s"%type)
		buf.append("\t\t\t'%s': %s,"%(name.lower(), path))
	return "\n".join(buf)


def main():
	stuff = getDecodedDataFromGbin(sys.argv[1])
	fieldSequence = getFieldSequenceForInstance(stuff[0], "obj")
	className = stuff[0].get_class().name.split(".")[-1]
	print makePythonExpression(fieldSequence, className)


if __name__=="__main__":
	main()
