/*
 * @(#)$Id$
 *
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 2001, Sun
 * Microsystems., http://www.sun.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 * @author Jacek Ambroziak
 * @author Santiago Pericas-Geertsen
 *
 */

package org.apache.xalan.xsltc.compiler;

import java.util.ArrayList;

import org.apache.xalan.xsltc.compiler.util.Type;
import org.apache.xalan.xsltc.compiler.util.ReferenceType;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.generic.*;
import org.apache.bcel.classfile.Field;

import org.apache.xalan.xsltc.compiler.util.*;

final class Number extends Instruction implements Closure {
    private static final int LEVEL_SINGLE   = 0;
    private static final int LEVEL_MULTIPLE = 1;
    private static final int LEVEL_ANY      = 2;

    static final private String[] ClassNames = { 
	"org.apache.xalan.xsltc.dom.SingleNodeCounter",	  // LEVEL_SINGLE
	"org.apache.xalan.xsltc.dom.MultipleNodeCounter", // LEVEL_MULTIPLE
	"org.apache.xalan.xsltc.dom.AnyNodeCounter"	  // LEVEL_ANY
    };

    static final private String[] FieldNames = { 
	"___single_node_counter",		   // LEVEL_SINGLE
	"___multiple_node_counter",		   // LEVEL_MULTIPLE
	"___any_node_counter"			   // LEVEL_ANY
    };

    private Pattern _from = null;
    private Pattern _count = null;
    private Expression _value = null;

    private AttributeValueTemplate _lang = null;
    private AttributeValueTemplate _format = null;
    private AttributeValueTemplate _letterValue = null;
    private AttributeValueTemplate _groupingSeparator = null;
    private AttributeValueTemplate _groupingSize = null;

    private int _level = LEVEL_SINGLE;
    private boolean _formatNeeded = false;

    private String _className = null;
    private ArrayList _closureVars = null;

     // -- Begin Closure interface --------------------

    /**
     * Returns true if this closure is compiled in an inner class (i.e.
     * if this is a real closure).
     */
    public boolean inInnerClass() {
	return (_className != null);
    }

    /**
     * Returns a reference to its parent closure or null if outermost.
     */
    public Closure getParentClosure() {
	return null;
    }

    /**
     * Returns the name of the auxiliary class or null if this predicate 
     * is compiled inside the Translet.
     */
    public String getInnerClassName() {
	return _className;
    }

    /**
     * Add new variable to the closure.
     */
    public void addVariable(VariableRefBase variableRef) {
	if (_closureVars == null) {
	    _closureVars = new ArrayList();
	}

	// Only one reference per variable
	if (!_closureVars.contains(variableRef)) {
	    _closureVars.add(variableRef);
	}
    }

    // -- End Closure interface ----------------------

   public void parseContents(Parser parser) {
	final int count = _attributes.getLength();

	for (int i = 0; i < count; i++) {
	    final String name = _attributes.getQName(i);
	    final String value = _attributes.getValue(i);

	    if (name.equals("value")) {
		_value = parser.parseExpression(this, name, null);
	    }
	    else if (name.equals("count")) {
		_count = parser.parsePattern(this, name, null);
	    }
	    else if (name.equals("from")) {
		_from = parser.parsePattern(this, name, null);
	    }
	    else if (name.equals("level")) {
		if (value.equals("single")) {
		    _level = LEVEL_SINGLE;
		}
		else if (value.equals("multiple")) {
		    _level = LEVEL_MULTIPLE;
		}
		else if (value.equals("any")) {
		    _level = LEVEL_ANY;
		}
	    }
	    else if (name.equals("format")) {
		_format = new AttributeValueTemplate(value, parser, this);
		_formatNeeded = true;
	    }
	    else if (name.equals("lang")) {
		_lang = new AttributeValueTemplate(value, parser, this);
		_formatNeeded = true;
	    }
	    else if (name.equals("letter-value")) {
		_letterValue = new AttributeValueTemplate(value, parser, this);
		_formatNeeded = true;
	    }
	    else if (name.equals("grouping-separator")) {
		_groupingSeparator = new AttributeValueTemplate(value, parser, this);
		_formatNeeded = true;
	    }
	    else if (name.equals("grouping-size")) {
		_groupingSize = new AttributeValueTemplate(value, parser, this);
		_formatNeeded = true;
	    }
	}
    }

    public Type typeCheck(SymbolTable stable) throws TypeCheckError {
	if (_value != null) {
	    Type tvalue = _value.typeCheck(stable);
	    if (tvalue instanceof RealType == false) {
		_value = new CastExpr(_value, Type.Real);
	    }
	}
	if (_count != null) {
	    _count.typeCheck(stable);
	}
	if (_from != null) {
	    _from.typeCheck(stable);
	}
	if (_format != null) {
	    _format.typeCheck(stable);
	}
	if (_lang != null) {
	    _lang.typeCheck(stable);
	}
	if (_letterValue != null) {
	    _letterValue.typeCheck(stable);
	}
	if (_groupingSeparator != null) {
	    _groupingSeparator.typeCheck(stable);
	}
	if (_groupingSize != null) {
	    _groupingSize.typeCheck(stable);
	}
	return Type.Void;
    }

    /**
     * True if the has specified a value for this instance of number.
     */
    public boolean hasValue() {
	return _value != null;
    }

    /**
     * Returns <tt>true</tt> if this instance of number has neither
     * a from nor a count pattern.
     */
    public boolean isDefault() {
	return _from == null && _count == null;
    }

    private void compileDefault(ClassGenerator classGen,
			        MethodGenerator methodGen) {
	int index;
	ConstantPoolGen cpg = classGen.getConstantPool();
	InstructionList il = methodGen.getInstructionList();

	int[] fieldIndexes = getXSLTC().getNumberFieldIndexes();

	if (fieldIndexes[_level] == -1) {
	    Field defaultNode = new Field(ACC_PRIVATE, 
					  cpg.addUtf8(FieldNames[_level]),
					  cpg.addUtf8(NODE_COUNTER_SIG),
					  null, 
					  cpg.getConstantPool());

	    // Add a new private field to this class
	    classGen.addField(defaultNode);

	    // Get a reference to the newly added field
	    fieldIndexes[_level] = cpg.addFieldref(classGen.getClassName(), 
						   FieldNames[_level],
						   NODE_COUNTER_SIG);
	}

	// Check if field is initialized (runtime)
	il.append(classGen.loadTranslet());
	il.append(new GETFIELD(fieldIndexes[_level]));
	final BranchHandle ifBlock1 = il.append(new IFNONNULL(null));

	// Create an instance of DefaultNodeCounter
	index = cpg.addMethodref(ClassNames[_level],
				 "getDefaultNodeCounter", 
				 "(" + TRANSLET_INTF_SIG
				 + DOM_INTF_SIG
				 + NODE_ITERATOR_SIG 
				 + ")" + NODE_COUNTER_SIG);
	il.append(classGen.loadTranslet());
	il.append(methodGen.loadDOM());
	il.append(methodGen.loadIterator());
	il.append(new INVOKESTATIC(index));
	il.append(DUP);

	// Store the node counter in the field
	il.append(classGen.loadTranslet());
	il.append(SWAP);
	il.append(new PUTFIELD(fieldIndexes[_level]));
	final BranchHandle ifBlock2 = il.append(new GOTO(null));

	// Backpatch conditionals
	ifBlock1.setTarget(il.append(classGen.loadTranslet()));
	il.append(new GETFIELD(fieldIndexes[_level]));
	
	ifBlock2.setTarget(il.append(NOP));
    }

    /**
     * Compiles a constructor for the class <tt>_className</tt> that
     * inherits from {Any,Single,Multiple}NodeCounter. This constructor
     * simply calls the same constructor in the super class.
     */
    private void compileConstructor(ClassGenerator classGen) {
	MethodGenerator cons;
	final InstructionList il = new InstructionList();
	final ConstantPoolGen cpg = classGen.getConstantPool();

	cons = new MethodGenerator(ACC_PUBLIC,
				   org.apache.bcel.generic.Type.VOID, 
				   new org.apache.bcel.generic.Type[] {
				       Util.getJCRefType(TRANSLET_INTF_SIG),
				       Util.getJCRefType(DOM_INTF_SIG),
				       Util.getJCRefType(NODE_ITERATOR_SIG)
				   },
				   new String[] {
				       "dom",
				       "translet",
				       "iterator"
				   },
				   "<init>", _className, il, cpg);

	il.append(ALOAD_0);     // this
	il.append(ALOAD_1);     // translet
	il.append(ALOAD_2);     // DOM
	il.append(new ALOAD(3));// iterator

	int index = cpg.addMethodref(ClassNames[_level],
				     "<init>", 
				     "(" + TRANSLET_INTF_SIG
				     + DOM_INTF_SIG
				     + NODE_ITERATOR_SIG 
				     + ")V");
	il.append(new INVOKESPECIAL(index));
	il.append(RETURN);
	
	cons.stripAttributes(true);
	cons.setMaxLocals();
	cons.setMaxStack();
	classGen.addMethod(cons.getMethod());
    }

    /**
     * This method compiles code that is common to matchesFrom() and
     * matchesCount() in the auxillary class.
     */
    private void compileLocals(NodeCounterGenerator nodeCounterGen,
			       MatchGenerator matchGen,
			       InstructionList il) 
    {
	int field;
	LocalVariableGen local;
	ConstantPoolGen cpg = nodeCounterGen.getConstantPool();

	// Get NodeCounter._iterator and store locally
	local = matchGen.addLocalVariable("iterator", 
					  Util.getJCRefType(NODE_ITERATOR_SIG),
					  null, null);
	field = cpg.addFieldref(NODE_COUNTER, "_iterator",
				ITERATOR_FIELD_SIG);
	il.append(ALOAD_0); // 'this' pointer on stack
	il.append(new GETFIELD(field));
	il.append(new ASTORE(local.getIndex()));
	matchGen.setIteratorIndex(local.getIndex());
	
	// Get NodeCounter._translet and store locally
	local = matchGen.addLocalVariable("translet", 
				  Util.getJCRefType(TRANSLET_SIG),
				  null, null);
	field = cpg.addFieldref(NODE_COUNTER, "_translet",
				"Lorg/apache/xalan/xsltc/Translet;");
	il.append(ALOAD_0); // 'this' pointer on stack
	il.append(new GETFIELD(field));
	il.append(new CHECKCAST(cpg.addClass(TRANSLET_CLASS)));
	il.append(new ASTORE(local.getIndex()));
	nodeCounterGen.setTransletIndex(local.getIndex());

	// Get NodeCounter._document and store locally
	local = matchGen.addLocalVariable("document", 
					  Util.getJCRefType(DOM_INTF_SIG),
					  null, null);
	field = cpg.addFieldref(_className, "_document", DOM_INTF_SIG);
	il.append(ALOAD_0); // 'this' pointer on stack
	il.append(new GETFIELD(field));
	// Make sure we have the correct DOM type on the stack!!!
	il.append(new ASTORE(local.getIndex()));
	matchGen.setDomIndex(local.getIndex());
    }

    private void compilePatterns(ClassGenerator classGen,
				 MethodGenerator methodGen) 
    {
	int current;
	int field;
	LocalVariableGen local;
	MatchGenerator matchGen;
	NodeCounterGenerator nodeCounterGen;

	_className = getXSLTC().getHelperClassName();
	nodeCounterGen = new NodeCounterGenerator(_className,
						  ClassNames[_level],
						  toString(), 
						  ACC_PUBLIC | ACC_SUPER,
						  null,
						  classGen.getStylesheet());
	InstructionList il = null;
	ConstantPoolGen cpg = nodeCounterGen.getConstantPool();

	// Add a new instance variable for each var in closure
	final int closureLen = (_closureVars == null) ? 0 : 
	    _closureVars.size();

	for (int i = 0; i < closureLen; i++) {
	    VariableBase var = 
		((VariableRefBase) _closureVars.get(i)).getVariable();

	    nodeCounterGen.addField(new Field(ACC_PUBLIC, 
					cpg.addUtf8(var.getVariable()),
					cpg.addUtf8(var.getType().toSignature()),
					null, cpg.getConstantPool()));
	}

	// Add a single constructor to the class
	compileConstructor(nodeCounterGen);

	/*
	 * Compile method matchesFrom()
	 */
	if (_from != null) {
	    il = new InstructionList();
	    matchGen =
		new MatchGenerator(ACC_PUBLIC | ACC_FINAL,
				   org.apache.bcel.generic.Type.BOOLEAN, 
				   new org.apache.bcel.generic.Type[] {
				       org.apache.bcel.generic.Type.INT,
				   },
				   new String[] {
				       "node",
				   },
				   "matchesFrom", _className, il, cpg);

	    compileLocals(nodeCounterGen,matchGen,il);

	    // Translate Pattern
	    il.append(matchGen.loadContextNode());
	    _from.translate(nodeCounterGen, matchGen);
	    _from.synthesize(nodeCounterGen, matchGen);
	    il.append(IRETURN);
		    
	    matchGen.stripAttributes(true);
	    matchGen.setMaxLocals();
	    matchGen.setMaxStack();
	    matchGen.removeNOPs();
	    nodeCounterGen.addMethod(matchGen.getMethod());
	}

	/*
	 * Compile method matchesCount()
	 */
	if (_count != null) {
	    il = new InstructionList();
	    matchGen = new MatchGenerator(ACC_PUBLIC | ACC_FINAL,
					  org.apache.bcel.generic.Type.BOOLEAN, 
					  new org.apache.bcel.generic.Type[] {
					      org.apache.bcel.generic.Type.INT,
					  },
					  new String[] {
					      "node",
					  },
					  "matchesCount", _className, il, cpg);

	    compileLocals(nodeCounterGen,matchGen,il);
	    
	    // Translate Pattern
	    il.append(matchGen.loadContextNode());
	    _count.translate(nodeCounterGen, matchGen);
	    _count.synthesize(nodeCounterGen, matchGen);
	    
	    il.append(IRETURN);
		    
	    matchGen.stripAttributes(true);
	    matchGen.setMaxLocals();
	    matchGen.setMaxStack();
	    matchGen.removeNOPs();
	    nodeCounterGen.addMethod(matchGen.getMethod());
	}
	
	getXSLTC().dumpClass(nodeCounterGen.getJavaClass());

	// Push an instance of the newly created class
	cpg = classGen.getConstantPool();
	il = methodGen.getInstructionList();

	final int index = cpg.addMethodref(_className, "<init>", 
					   "(" + TRANSLET_INTF_SIG
					   + DOM_INTF_SIG 
					   + NODE_ITERATOR_SIG
					   + ")V");
	il.append(new NEW(cpg.addClass(_className)));
	il.append(DUP);
	il.append(classGen.loadTranslet());
	il.append(methodGen.loadDOM());
	il.append(methodGen.loadIterator());
	il.append(new INVOKESPECIAL(index));

	// Initialize closure variables
	for (int i = 0; i < closureLen; i++) {
	    final VariableRefBase varRef = (VariableRefBase) _closureVars.get(i);
	    final VariableBase var = varRef.getVariable();
	    final Type varType = var.getType();

	    // Store variable in new closure
	    il.append(DUP);
	    il.append(var.loadInstruction());
	    il.append(new PUTFIELD(
		    cpg.addFieldref(_className, var.getVariable(), 
			varType.toSignature())));
	}
    }

    public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
	int index;
	final ConstantPoolGen cpg = classGen.getConstantPool();
	final InstructionList il = methodGen.getInstructionList();

	// Push "this" for the call to characters()
	il.append(classGen.loadTranslet());

	if (hasValue()) {
	    compileDefault(classGen, methodGen);
	    _value.translate(classGen, methodGen);

	    // Round the number to the nearest integer
	    index = cpg.addMethodref(MATH_CLASS, "round", "(D)J");
	    il.append(new INVOKESTATIC(index));
	    il.append(new L2I());

	    // Call setValue on the node counter
	    index = cpg.addMethodref(NODE_COUNTER, 
				     "setValue", 
				     "(I)" + NODE_COUNTER_SIG);
	    il.append(new INVOKEVIRTUAL(index));
	}
	else if (isDefault()) {
	    compileDefault(classGen, methodGen);
	}
	else {
	    compilePatterns(classGen, methodGen);
	}

	// Call setStartNode() 
	if (!hasValue()) {
	    il.append(methodGen.loadContextNode());
	    index = cpg.addMethodref(NODE_COUNTER, 
				     SET_START_NODE, 
				     "(I)" + NODE_COUNTER_SIG);
	    il.append(new INVOKEVIRTUAL(index));
	}

	// Call getCounter() with or without args
	if (_formatNeeded) {
	    if (_format != null) {
		_format.translate(classGen, methodGen);
	    }
	    else {
		il.append(new PUSH(cpg, "1"));
	    }

	    if (_lang != null) {
		_lang.translate(classGen, methodGen);
	    }
	    else {
		il.append(new PUSH(cpg, "en")); 	// TODO ??
	    }

	    if (_letterValue != null) {
		_letterValue.translate(classGen, methodGen);
	    }
	    else {
		il.append(new PUSH(cpg, Constants.EMPTYSTRING));
	    }

	    if (_groupingSeparator != null) {
		_groupingSeparator.translate(classGen, methodGen);
	    }
	    else {
		il.append(new PUSH(cpg, Constants.EMPTYSTRING));
	    }

	    if (_groupingSize != null) {
		_groupingSize.translate(classGen, methodGen);
	    }
	    else {
		il.append(new PUSH(cpg, "0"));
	    }

	    index = cpg.addMethodref(NODE_COUNTER, "getCounter", 
				     "(" + STRING_SIG + STRING_SIG 
				     + STRING_SIG + STRING_SIG 
				     + STRING_SIG + ")" + STRING_SIG);
	    il.append(new INVOKEVIRTUAL(index));
	}
	else {
	    index = cpg.addMethodref(NODE_COUNTER, "setDefaultFormatting", 
				     "()" + NODE_COUNTER_SIG);
	    il.append(new INVOKEVIRTUAL(index));

	    index = cpg.addMethodref(NODE_COUNTER, "getCounter", 
				     "()" + STRING_SIG);
	    il.append(new INVOKEVIRTUAL(index));
	}

	// Output the resulting string to the handler
	il.append(methodGen.loadHandler());
	index = cpg.addMethodref(TRANSLET_CLASS,
				 CHARACTERSW,
				 CHARACTERSW_SIG);
	il.append(new INVOKEVIRTUAL(index));
    }
}
