# -*- coding: utf-8 -*-
"""
Make an expression for our custom grammars that builds the output record
of a grammar for a particular data type.

Use is as python /data/gavo/inputs/gums/bin/getschema.py <file>

This ought to be moved into the base of the res/xgrammars.
"""

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

from gavo import base
sys.path.append(os.path.join(base.getConfig("inputsDir"), "gums", "res"))
import javaobj


def getFieldSequenceForInstance(instance, attPath):
	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))
			else:
				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)
		


CONVERTER_TEMPLATE = """/*
Generated by gums/bin/getschema.py.  Do not edit here but there.

Thanks to Thomas Brüsemeister for writing up a template. */

package gaia.cu3.gbin2ascii.converter;

import gaia.cu1.mdb.cu2.um.umtypes.dm.%(interfaceName)s;
import gaia.cu1.mdb.cu2.um.umtypes.dmimpl.%(typeName)s;
import gaia.cu1.tools.dal.gbin.GbinFactory;
import gaia.cu1.tools.dal.gbin.GbinReader;
import gaia.cu1.tools.exception.GaiaDataAccessException;
import gaia.cu1.tools.exception.GaiaException;

import java.io.File;
import java.io.PrintStream;
import java.io.IOException;

public class %(interfaceName)sAsciiConverter implements Converter {
    @Override
    public void convert(File f, PrintStream outF) throws IOException{

        GbinReader<%(typeName)s> gbinReader= null;

        try {

            gbinReader = GbinFactory.getGbinReader(f);

            while (gbinReader.hasNext()) {

                %(typeName)s obj = gbinReader.next();

%(bufferBuildingCode)s

            }


        } catch (GaiaException e) {

            System.err.println("Got a " + e.getClass().getSimpleName() + " :" + e.getMessage());

        } finally {

            if (gbinReader != null)

                try {
                    gbinReader.close();
                } catch (GaiaDataAccessException e) {

                    System.err.println("Got a " + e.getClass().getSimpleName() + " :" + e.getMessage());
                }
        }
    }

}
"""

def makeJavaConverter(fieldSequence, typeName):
	bufferBuildingCode = []
	interfaceName = re.sub("(.*)Impl$", r"\1", typeName)
	for name, path, type in fieldSequence:
		if path is None:
			continue

		# hack in accessor baroqueness, twice if necessary
		path = re.sub(r"([^.]*)\.(.)([^.]*)\.([^.]*)",
			lambda m: "%s.get%s%s().%s"%(
				m.group(1), m.group(2).upper(), m.group(3), m.group(4)),
			path)
		path = re.sub(r"\.([^.]*)$",
			lambda mat: ".get"+mat.group(1)[0].upper()+mat.group(1)[1:]+"()", path)
		bufferBuildingCode.extend([path, '"|"'])

	# we don't want a trailing vbar
	del bufferBuildingCode[-1]
	bufferBuildingCode = "outF.println(%s);"%("+".join(bufferBuildingCode))
	return  CONVERTER_TEMPLATE%locals()


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

if __name__=="__main__":
	main()

