/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.bsf.util;

import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Hashtable;
import java.util.Stack;
import java.util.Vector;

import org.apache.bsf.util.cf.CodeFormatter;

/**
 * A <code>CodeBuffer</code> object is used as a code repository for generated Java code.
 * It provides buffers which correspond to the various sections of a Java class.
 * 
 * @author   Matthew J. Duftler
 */
public class CodeBuffer
{
  private StringWriter fieldDeclSW       = new StringWriter(),
                       methodDeclSW      = new StringWriter(),
                       initializerSW     = new StringWriter(),
                       constructorSW     = new StringWriter(),
                       serviceMethodSW   = new StringWriter();

  private PrintWriter  fieldDeclPW       = new PrintWriter(fieldDeclSW),
                       methodDeclPW      = new PrintWriter(methodDeclSW),
                       initializerPW     = new PrintWriter(initializerSW),
                       constructorPW     = new PrintWriter(constructorSW),
                       serviceMethodPW   = new PrintWriter(serviceMethodSW);

  private Stack        symbolTableStack  = new Stack();
  private Hashtable    symbolTable       = new Hashtable(),
                       usedSymbolIndices = new Hashtable();

  private ObjInfo      finalStatementInfo;
  private CodeBuffer   parent;


  {
    symbolTableStack.push(symbolTable);
  }

  // New stuff...
  private Vector imports                 = new Vector(),
                 constructorArguments    = new Vector(),
                 constructorExceptions   = new Vector(),
                 serviceMethodExceptions = new Vector(),
                 implementsVector        = new Vector();
  private String packageName             = null,
                 className               = "Test",
                 serviceMethodName       = "exec",
                 extendsName             = null;
  private Class  serviceMethodReturnType = void.class;

  public CodeBuffer()
  {
  }
  public CodeBuffer(CodeBuffer parent)
  {
    this.parent = parent;
  }
  public void addConstructorArgument(ObjInfo arg)
  {
    constructorArguments.addElement(arg);
  }
  public void addConstructorException(String exceptionName)
  {
    if (!constructorExceptions.contains(exceptionName))
    {
      constructorExceptions.addElement(exceptionName);
    }
  }
  public void addConstructorStatement(String statement)
  {
    constructorPW.println(statement);
  }
  public void addFieldDeclaration(String statement)
  {
    fieldDeclPW.println(statement);
  }
  public void addImplements(String importName)
  {
    if (!implementsVector.contains(importName))
    {
      implementsVector.addElement(importName);
    }
  }
  public void addImport(String importName)
  {
    if (!imports.contains(importName))
    {
      imports.addElement(importName);
    }
  }
  public void addInitializerStatement(String statement)
  {
    initializerPW.println(statement);
  }
  public void addMethodDeclaration(String statement)
  {
    methodDeclPW.println(statement);
  }
  public void addServiceMethodException(String exceptionName)
  {
    if (!serviceMethodExceptions.contains(exceptionName))
    {
      serviceMethodExceptions.addElement(exceptionName);
    }
  }
  public void addServiceMethodStatement(String statement)
  {
    serviceMethodPW.println(statement);
  }
  // Used internally by merge(...).
  private void appendIfNecessary(PrintWriter pw, StringBuffer buf)
  {
    if (buf.length() > 0)
    {
      pw.print(buf.toString());
    }
  }
  public String buildNewSymbol(String prefix)
  {
    Integer nextNum = getSymbolIndex(prefix);

    if (nextNum == null)
    {
      nextNum = new Integer(0);
    }

    int    iNextNum = nextNum.intValue();
    String symbol   = prefix + "_" + iNextNum;

    while (getSymbol(symbol) != null)
    {
      iNextNum++;
      symbol = prefix + "_" + iNextNum;
    }

    putSymbolIndex(prefix, new Integer(iNextNum + 1));

    return symbol;
  }
  public void clearSymbolTable()
  {
    symbolTable       = new Hashtable();
    symbolTableStack  = new Stack();
    symbolTableStack.push(symbolTable);

    usedSymbolIndices = new Hashtable();
  }
  public String getClassName()
  {
    return className;
  }
  public Vector getConstructorArguments()
  {
    return constructorArguments;
  }
  public StringBuffer getConstructorBuffer()
  {
    constructorPW.flush();

    return constructorSW.getBuffer();
  }
  public Vector getConstructorExceptions()
  {
    return constructorExceptions;
  }
  public String getExtends()
  {
    return extendsName;
  }
  public StringBuffer getFieldBuffer()
  {
    fieldDeclPW.flush();

    return fieldDeclSW.getBuffer();
  }
  public ObjInfo getFinalServiceMethodStatement()
  {
    return finalStatementInfo;
  }
  public Vector getImplements()
  {
    return implementsVector;
  }
  public Vector getImports()
  {
    return imports;
  }
  public StringBuffer getInitializerBuffer()
  {
    initializerPW.flush();

    return initializerSW.getBuffer();
  }
  public StringBuffer getMethodBuffer()
  {
    methodDeclPW.flush();

    return methodDeclSW.getBuffer();
  }
  public String getPackageName()
  {
    return packageName;
  }
  public StringBuffer getServiceMethodBuffer()
  {
    serviceMethodPW.flush();

    return serviceMethodSW.getBuffer();
  }
  public Vector getServiceMethodExceptions()
  {
    return serviceMethodExceptions;
  }
  public String getServiceMethodName()
  {
    return serviceMethodName;
  }
  public Class getServiceMethodReturnType()
  {
    if (finalStatementInfo != null)
    {
      return finalStatementInfo.objClass;
    }
    else if (serviceMethodReturnType != null)
    {
      return serviceMethodReturnType;
    }
    else
    {
      return void.class;
    }
  }
  public ObjInfo getSymbol(String symbol)
  {
    ObjInfo ret = (ObjInfo)symbolTable.get(symbol);

    if (ret == null && parent != null)
      ret = parent.getSymbol(symbol);

    return ret;
  }
  Integer getSymbolIndex(String prefix)
  {
    if (parent != null)
    {
      return parent.getSymbolIndex(prefix);
    }
    else
    {
      return (Integer)usedSymbolIndices.get(prefix);
    }
  }
  public Hashtable getSymbolTable()
  {
    return symbolTable;
  }
  public void merge(CodeBuffer otherCB)
  {
    Vector otherImports = otherCB.getImports();

    for (int i = 0; i < otherImports.size(); i++)
    {
      addImport((String)otherImports.elementAt(i));
    }

    appendIfNecessary(fieldDeclPW,     otherCB.getFieldBuffer());
    appendIfNecessary(methodDeclPW,    otherCB.getMethodBuffer());
    appendIfNecessary(initializerPW,   otherCB.getInitializerBuffer());
    appendIfNecessary(constructorPW,   otherCB.getConstructorBuffer());
    appendIfNecessary(serviceMethodPW, otherCB.getServiceMethodBuffer());

    ObjInfo oldRet = getFinalServiceMethodStatement();

    if (oldRet != null && oldRet.isExecutable())
    {
      addServiceMethodStatement(oldRet.objName + ";");
    }

    setFinalServiceMethodStatement(otherCB.getFinalServiceMethodStatement());
  }
  public void popSymbolTable()
  {
    symbolTableStack.pop();
    symbolTable = (Hashtable)symbolTableStack.peek();
  }
  public void print(PrintWriter out, boolean formatOutput)
  {
    if (formatOutput)
    {
      new CodeFormatter().formatCode(new StringReader(toString()), out);
    }
    else
    {
      out.print(toString());
    }

    out.flush();
  }
  public void pushSymbolTable()
  {
    symbolTable = (Hashtable)symbolTableStack.push(new ScriptSymbolTable(symbolTable));
  }
  public void putSymbol(String symbol, ObjInfo obj)
  {
    symbolTable.put(symbol, obj);
  }
  void putSymbolIndex(String prefix, Integer index)
  {
    if (parent != null)
    {
      parent.putSymbolIndex(prefix, index);
    }
    else
    {
      usedSymbolIndices.put(prefix, index);
    }
  }
  public void setClassName(String className)
  {
    this.className = className;
  }
  public void setExtends(String extendsName)
  {
    this.extendsName = extendsName;
  }
  public void setFinalServiceMethodStatement(ObjInfo finalStatementInfo)
  {
    this.finalStatementInfo = finalStatementInfo;
  }
  public void setPackageName(String packageName)
  {
    this.packageName = packageName;
  }
  public void setServiceMethodName(String serviceMethodName)
  {
    this.serviceMethodName = serviceMethodName;
  }
  public void setServiceMethodReturnType(Class serviceMethodReturnType)
  {
    this.serviceMethodReturnType = serviceMethodReturnType;
  }
  public void setSymbolTable(Hashtable symbolTable)
  {
    this.symbolTable = symbolTable;
  }
  public boolean symbolTableIsStacked()
  {
    return (symbolTable instanceof ScriptSymbolTable);
  }
  public String toString()
  {
    StringWriter sw  = new StringWriter();
    PrintWriter  pw  = new PrintWriter(sw);
    ObjInfo      ret = finalStatementInfo;

    if (packageName != null && !packageName.equals(""))
    {
      pw.println("package " + packageName + ";");
      pw.println();
    }

    if (imports.size() > 0)
    {
      for (int i = 0; i < imports.size(); i++)
      {
        pw.println("import " + imports.elementAt(i) + ";");
      }

      pw.println();
    }

    pw.println("public class " + className +
               (extendsName != null && !extendsName.equals("")
                ? " extends " + extendsName
                : "") +
               (implementsVector.size() > 0
                ? " implements " +
                  StringUtils.getCommaListFromVector(implementsVector)
                : "")
              );
    pw.println("{");

    pw.print(getFieldBuffer().toString());

    StringBuffer buf = getInitializerBuffer();

    if (buf.length() > 0)
    {
      pw.println();
      pw.println("{");
      pw.print(buf.toString());
      pw.println("}");
    }

    buf = getConstructorBuffer();

    if (buf.length() > 0)
    {
      pw.println();
      pw.println("public " + className + "(" +
                 (constructorArguments.size() > 0
                  ? StringUtils.getCommaListFromVector(constructorArguments)
                  : ""
                 ) + ")" +
                 (constructorExceptions.size() > 0
                  ? " throws " +
                    StringUtils.getCommaListFromVector(constructorExceptions)
                  : ""
                 )
                );
      pw.println("{");
      pw.print(buf.toString());
      pw.println("}");
    }

    buf = getServiceMethodBuffer();

    if (buf.length() > 0 || ret != null)
    {
      pw.println();
      pw.println("public " +
                  StringUtils.getClassName(getServiceMethodReturnType()) + " " +
                  serviceMethodName + "()" +
                 (serviceMethodExceptions.size() > 0
                  ? " throws " +
                    StringUtils.getCommaListFromVector(serviceMethodExceptions)
                  : ""
                 )
                );
      pw.println("{");

      pw.print(buf.toString());

      if (ret != null)
      {
        if (ret.isValueReturning())
        {
          pw.println();
          pw.println("return " + ret.objName + ";");
        }
        else if (ret.isExecutable())
        {
          pw.println(ret.objName + ";");
        }
      }

      pw.println("}");
    }

    pw.print(getMethodBuffer().toString());

    pw.println("}");

    pw.flush();

    return sw.toString();
  }
}
