package org.ephman.abra.tools.generators;

import org.ephman.abra.tools.*;
import org.ephman.utils.Tokenizer;
import org.ephman.abra.tools.plugins.*;

import java.io.*;
import java.util.*;

import org.apache.regexp.*;
/**
 *
 * generate the PHP-Nuke code for a table
 * @author Paul M. Bethe
 * @version 0.0.1 (2/2005)
 */

public class PhpGenerator extends GeneratorPlugin {

	final String [] cNames = {"php"};
	final String [] fNames = {"php"};

	public String [] getClassLevelNodeNames () { return cNames; }
	public String [] getFieldLevelNodeNames () { return fNames; }

	protected boolean hasDefault () { return false; }

        String getDefaultName (JClass currentClass) {
	    return  "all_" + currentClass.getTableName();
	}

	protected ClassPluginData createDefault (JClass currentClass) {
		String name = getDefaultName (currentClass);
		return new PhpPluginData (name, getDefaultFormatName ());
	}

	public String getName () { return "PhpGenerator";};
	/** call back when the node 'validator' which has been registered by this class is encountered
	 * @param nodeName should be validator
	 * @param attributes all the attributes in the xml node in key-value hmap
	 *   looking for name="fully-qualified class name" and format="mt54x" etc.
	 * @param currentClass the JClass on which this node occured
	 *
	 * @throws SchemaException if the data is invalid.
	 */
	public void handleClassLevelNode (String nodeName, Map attributes, JClass currentClass) 
		throws SchemaException {
		String format = (String)attributes.get ("name");
		String name = format + "_" + currentClass.getTableName ();
		String entry_cols = (String)attributes.get ("entry_cols");
		String genNew = (String)attributes.get ("new");
		String genUpdate = (String)attributes.get ("update");

		assertMandatory (format, "name");
		PhpPluginData plugin = new PhpPluginData (name, format, entry_cols, genNew, genUpdate);
		registerPlugin (plugin, currentClass);
	}

	/** call back when the node 'nodeName' which has been registered by this class is encountered
	 * @param nodeName the node name ie "php"
	 * @param attributes all the attributes in the xml node in key-value hmap
	 * @param currentClass the JClass on which this node occured
	 * @param currentField the JField on which this node occured
	 *
	 * @throws SchemaException if the data is invalid.
	 */
    public void handleFieldLevelNode (String nodeName, Map attributes, 
				      JClass currentClass, JField currentField) 
		throws SchemaException {
	
	String name = (String)attributes.get ("name"); // ??
	String dim = (String)attributes.get ("dim");
	String update = (String)attributes.get ("update");
	String formatStr = (String)attributes.get ("format");
	Vector formats = Tokenizer.tokenize (formatStr, ",", "'");
	for (int i=0; formats != null && i < formats.size (); i++) {
	    String format = (String)formats.elementAt (i);
		if (!Checks.exists (format))
		    format = getDefaultFormatName ();
		PhpField pf  = new PhpField (dim, name, update);
		pf.setJField (currentField);
		super.handleFieldLevelNode (pf, format, currentClass);
	}
    }

	public void close () {
		// nothing
	}

	///
	private String outdir;
	private char fileSeperator;
	
	public PhpGenerator () {
		this.outdir = MapToJava.outdir;
		this.fileSeperator = MapToJava.fileSeperator.charAt (0);
	}

	public void generate (JClass currentClass) throws IOException, SchemaException {
		Map validators = getNamedMap (currentClass);
		Iterator valNames = validators.keySet ().iterator ();
		while (valNames.hasNext ()) {
			String thisValName = (String)valNames.next ();
			PhpPluginData thisPlugin = (PhpPluginData)validators.get (thisValName);
			String updName = (thisPlugin.getName ()).replace ('.', fileSeperator);
			String newName = updName + "_new";
			String updateName = updName + "_update";
			String displayName = updName + "_display";

			if (thisPlugin.genUpdate) {
			    String fileName = outdir + fileSeperator + updateName+ ".inc";
			    FileWriter updFile = new FileWriter (fileName);
			    Debugger.trace ("Generating php update " + fileName, Debugger.VERBOSE);
			    writeUpdateCode (updFile, thisPlugin, currentClass);
			    updFile.close ();
			}
			if (thisPlugin.genNew) {
			    String fileName = outdir + fileSeperator + newName+ ".inc";
			    FileWriter updFile = new FileWriter (fileName);
			    Debugger.trace ("Generating php new " + fileName, Debugger.VERBOSE);
			    writeInsertCode (updFile, thisPlugin, currentClass);
			    updFile.close ();
			}

		}
	}

    String gen_prefix = "<?php\n/** do not edit this file -- generated code (your changes will be overwritten */\n\n";

    void writeUpdateCode (Writer updFile, PhpPluginData thisPlugin, JClass currentClass) throws IOException, SchemaException {
	Vector allFields = thisPlugin.getAllFields ();
	String stmt = "$update_stmt = \"update " + currentClass.getTableName() + " set ";

	for (int f=0; f<allFields.size(); f++) {
	    PhpField pf = (PhpField)allFields.elementAt(f);
	    if (pf.doUpdate ()) {
		JField jf = pf.getJField ();
		String nm = jf.getSqlName ();
		
		if (f>0) stmt += ", ";
		stmt += nm + "='$chng_";
		if (pf.hasInField ()) nm = pf.getInField(); /* change the var name ... */
		stmt += nm + "'";
	    }
	}
	stmt += "\";\n?>\n";
	updFile.write(gen_prefix);
	updFile.write(stmt);
    }

    void writeInsertCode (Writer updFile, PhpPluginData thisPlugin, JClass currentClass) throws IOException, SchemaException {
	Vector allFields = thisPlugin.getAllFields ();

	String stmt = "$insert_stmt = \"insert into " + currentClass.getTableName() + " (";
	String val_part = "$insert_stmt .= \"VALUES (";

	for (int f=0; f<allFields.size(); f++) {
	    PhpField pf = (PhpField)allFields.elementAt(f);
	    JField jf = pf.getJField ();
	    String nm = jf.getSqlName ();


	    if (f>0) { stmt += ", "; val_part+=", "; }
	    stmt += nm;
	    if (pf.hasInField ()) nm = pf.getInField();
	    val_part += "'$add_" + nm + "'";
	}
	stmt += ") \";\n";
	val_part += ")\";\n?>\n";
	updFile.write(gen_prefix);
	updFile.write(stmt);
	updFile.write(val_part);
    }

    
}
