/*******************************************************************************
 *	GenBDataPy.cc	BEAM Data output
 *			T.Barnaby,	BEAM Ltd,	12/9/03
 *******************************************************************************
 */
#define	DEBUG	1

#include <stdio.h>
#include <stdarg.h>
#include <strings.h>
#include <GenBDataPy.h>
#include <bidl.h>

BString GenBDataPy::getTypeName(Node* n, int data){
	BString	typeName;
	
	if(n->nodeType() == Node::TTYPELIST){
		return BString("BObjList");
	}
	else {
		typeName = n->name();
		if(typeName == "Int32"){
			if(data)
				return "BObjInt";
			else
				return "Int32";
		}
		else if(typeName == "Bool"){
			if(data)
				return "BObjInt";
			else
				return "Int32";
		}
		else if(typeName == "String"){
			if(data)
				return "BObjString";
			else
				return "BString";
		}
		else if(typeName == "Error")	return "BError";
		else if(typeName == "Date")	return "BObjDate";
		else if(typeName == "DateTime")	return "BObjDateTime";
		else if(typeName == "Id")	return "BObjId";
		else if(typeName == "ObjData")	return "BObjData";
		else return typeName;
	}
}

void GenBDataPy::produceImp(Node* n){
	BString		s;
	BString		t;
	BIter		i;
	BList<Node*>*	nl;
	BString		typeName;
	
	switch(n->nodeType()){
	case Node::TMODULE:
		omodule = n->name();
#ifdef ZAP
		ofileImp.writeLine(BString("namespace ") + omodule + " {\n");
		ofileImp.indentMore();
#endif
		if(omodule == "BData"){
			ofileImp.writeLine(BString("import lib") + omodule + ";\n");
			ofileImp.writeLine("\n");
		}

		for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){
			produceImp(n->nodes()[i]);
		}
#ifdef ZAP
		ofileImp.indentLess();
		ofileImp.writeLine("}\n");
#endif
		break;
	case Node::TLIST:
		for(n->nodes().start(i); !n->nodes().isEnd(i); n->nodes().next(i)){
			produceImp(n->nodes()[i]);
		}
		break;
	case Node::TSTRUCT:
		if((n->name() == "BObjData") || (n->name() == "BObject"))
			return;
			
		typeName = BString("") + n->name();
		ofileImp.writeLine(BString("# ") + typeName + " Object Implementation\n");
		
		if((n->nodes().number() == 2) && n->node(1)){
			ofileImp.writeLine(BString("class ") + typeName + "(" + getTypeName(n->node(1), 1) + "):\n");
			ofileImp.indentMore();
			ofileImp.writeLine("def __init__(s):\n");
			ofileImp.indentMore();
			ofileImp.writeLine(getTypeName(n->node(1), 1) + ".__init__(s);\n");
		}
		else {
			ofileImp.writeLine(BString("class ") + typeName + ":\n");
			ofileImp.indentMore();
			ofileImp.writeLine("def __init__(s):\n");
			ofileImp.indentMore();
		}
		ofileImp.writeLine("s.type = 0;\n");

		nl = &n->node(0)->nodes();
		for(nl->start(i); !nl->isEnd(i); nl->next(i)){
			t = getTypeName(nl->get(i)->node(0), 1);
			s = nl->get(i)->node(1)->name();
			ofileImp.writeLine(BString("s.") + s + " = " + t + "();\n");
			ofileImp.writeLine(BString("s.memberList.append(BNameValue(\"") + s + "\", s." + s + "));\n");
		}
		ofileImp.indentLess();
		ofileImp.indentLess();
		ofileImp.writeLine("\n");
		break;
	default:
		break;
	}
}

BError GenBDataPy::produceHeaderImp(){
	BError	err;

	ofileImp.printf("#############################################################################\n");
	ofileImp.printf("#\t%s\tProduced by Bidl\n", (ofileName + ".cc").retStr());
	ofileImp.printf("#############################################################################\n");
	ofileImp.printf("#\n");
	ofileImp.printf("\n");
	ofileImp.printf("import sys;\n\n");
	ofileImp.printf("sys.path.extend(['/usr/beam/lib']);\n\n");
	ofileImp.printf("from Beam import *;\n");
	ofileImp.printf("\n");
	return err;
}
BError GenBDataPy::produceTrailerImp(){
	BError	err;
	
	return err;
}

GenBDataPy::GenBDataPy(){
}

GenBDataPy::~GenBDataPy(){
}

BError GenBDataPy::produce(Node* n, BString fileName){
	BError	err;
	
//	dprintf("GenBDataPy::produce: %p\n", n);

	ofileName = fileName;
	ofileImp.open(ofileName + ".py", "w");
	
	// File Headers
	produceHeaderImp();
	
	// Generate code
	produceImp(n);

	// Generate trailers
	produceTrailerImp();
	ofileImp.close();

	return err;
}
