//  Copyright 2004 The Apache Software Foundation
//
// Licensed 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.tapestry.enhance.javassist;

import javassist.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tapestry.ApplicationRuntimeException;
import org.apache.tapestry.Tapestry;
import org.apache.tapestry.enhance.CodeGenerationException;
import org.apache.tapestry.enhance.MethodSignature;

import java.io.IOException;
import java.text.MessageFormat;

/**
 *  @author Mindbridge
 *  @version $Id$
 *  @since 3.0
 */
public class ClassFabricator
{
    private static final Log LOG = LogFactory.getLog(ClassFabricator.class);

    /**
     *  The code template for the standard property accessor method.    
     *                                      <p>
     *  Legend:                             <br>
     *      {0} = property field name       <br>
     */
    private static final String PROPERTY_ACCESSOR_TEMPLATE = "" +
        "'{'" +
        "  return {0}; " +
        "'}'";
        
    /**
     *  The code template for the standard property mutator method.    
     *                                      <p>
     *  Legend:                             <br>
     *      {0} = property field name       <br>
     */
    private static final String PROPERTY_MUTATOR_TEMPLATE = "" +
        "'{'" +
        "  {0} = $1; " +
        "'}'";
        
    /**
     *  The code template for the standard persistent property mutator method.    
     *                                      <p>
     *  Legend:                             <br>
     *      {0} = property field name       <br>
     *      {1} = property name             <br>
     */
    private static final String PERSISTENT_PROPERTY_MUTATOR_TEMPLATE =
        "" +
        "'{'" +
        "  {0} = $1;" +
        "  fireObservedChange(\"{1}\", {0}); " +
        "'}'";

    private ClassPool _classPool;
    private CtClass _genClass;

    public ClassFabricator(String className, CtClass parentClass, ClassPool classPool)
    {
        _classPool = classPool;
        _genClass = _classPool.makeClass(className, parentClass);
    }

    public CtField getField(String fieldName)
    {
        try
        {
            return _genClass.getField(fieldName);
        }
        catch (NotFoundException e)
        {
            return null;
        }
    }

    public void addInterface(Class interfaceType)
    {
        _genClass.addInterface(getCtClass(interfaceType));
    }

    public void createField(CtClass fieldType, String fieldName)
    {
        if (LOG.isDebugEnabled())
            LOG.debug("Creating field: " + fieldName);

        try
        {
            CtField field = new CtField(fieldType, fieldName, _genClass);
            _genClass.addField(field);
        }
        catch (CannotCompileException e)
        {
            throw new CodeGenerationException(e);
        }
    }

    public void createField(CtClass fieldType, String fieldName, String init)
    {
        if (LOG.isDebugEnabled())
            LOG.debug("Creating field: " + fieldName + " with initializer: " + init);

        try
        {
            CtField field = new CtField(fieldType, fieldName, _genClass);
            _genClass.addField(field, init);
        }
        catch (CannotCompileException e)
        {
            throw new CodeGenerationException(e);
        }
    }

    public CtMethod getMethod(String name, String signature)
    {
        try
        {
            return _genClass.getMethod(name, signature);
        }
        catch (NotFoundException e)
        {
            return null;
        }
    }

    public void addMethod(CtMethod method) throws CannotCompileException
    {
        _genClass.addMethod(method);
    }

    /**
     *  Constructs an accessor method name.
     * 
     **/

    public String buildMethodName(String prefix, String propertyName)
    {
        StringBuffer result = new StringBuffer(prefix);

        char ch = propertyName.charAt(0);

        result.append(Character.toUpperCase(ch));

        result.append(propertyName.substring(1));

        return result.toString();
    }

    public CtMethod createMethod(
        CtClass returnType,
        String methodName,
        CtClass[] arguments)
    {
        if (LOG.isDebugEnabled())
            LOG.debug("Creating method: " + methodName);

        CtMethod method = new CtMethod(returnType, methodName, arguments, _genClass);

        return method;
    }

    public CtMethod createAccessor(
        CtClass fieldType,
        String propertyName,
        String readMethodName)
    {
        String methodName =
            readMethodName == null ? buildMethodName("get", propertyName) : readMethodName;

        if (LOG.isDebugEnabled())
            LOG.debug("Creating accessor: " + methodName);

        CtMethod method = new CtMethod(fieldType, methodName, new CtClass[0], _genClass);

        return method;
    }

    /**
     *  Creates an accessor (getter) method for the property.
     * 
     *  @param fieldType the return type for the method
     *  @param fieldName the name of the field (not the name of the property)
     *  @param propertyName the name of the property (used to build the name of the method)
     *  @param readMethodName if not null, the name of the method to use
     * 
     **/

    public void createPropertyAccessor(
        CtClass fieldType,
        String fieldName,
        String propertyName,
        String readMethodName)
    {
        try
        {
            String accessorBody =
                MessageFormat.format(PROPERTY_ACCESSOR_TEMPLATE, new Object[] { fieldName, propertyName });

            CtMethod method = createAccessor(fieldType, propertyName, readMethodName);
            method.setBody(accessorBody);
            _genClass.addMethod(method);
        }
        catch (CannotCompileException e)
        {
            throw new CodeGenerationException(e);
        }
    }

    public CtMethod createMutator(
        CtClass fieldType,
        String propertyName)
    {
        String methodName = buildMethodName("set", propertyName);

        if (LOG.isDebugEnabled())
            LOG.debug("Creating mutator: " + methodName);

        CtMethod method =
            new CtMethod(CtClass.voidType, methodName, new CtClass[] { fieldType }, _genClass);

        return method;
    }

    /**
     *  Creates a mutator (aka "setter") method.
     * 
     *  @param fieldType type of field value (and type of parameter value)
     *  @param fieldName name of field (not property!)
     *  @param propertyName name of property (used to construct method name)
     *  @param isPersistent if true, adds a call to fireObservedChange()
     * 
     **/

    public void createPropertyMutator(
        CtClass fieldType,
        String fieldName,
        String propertyName,
        boolean isPersistent)
    {
        String bodyTemplate = isPersistent ? PERSISTENT_PROPERTY_MUTATOR_TEMPLATE : PROPERTY_MUTATOR_TEMPLATE;
        String body = MessageFormat.format(bodyTemplate, new Object[] { fieldName, propertyName });

        try
        {
            CtMethod method = createMutator(fieldType, propertyName);
            method.setBody(body);
            _genClass.addMethod(method);
        }
        catch (CannotCompileException e)
        {
            throw new CodeGenerationException(e);
        }
    }

    public CtClass getCtClass(Class searchClass)
    {
        String name = ClassFabUtils.getJavaClassName(searchClass);
        
        try
        {
            return _classPool.get(name);
        }
        catch (NotFoundException ex)
        {
            throw new ApplicationRuntimeException(Tapestry.format("unable-to-lookup", name, ex), ex);
        }
    }

    public void addMethod(int modifiers, MethodSignature ms, String body)
    {
        CtClass ctReturnType = getCtClass(ms.getReturnType());

        CtClass[] ctParameters = convertClasses(ms.getParameterTypes());
        CtClass[] ctExceptions = convertClasses(ms.getExceptionTypes());

        CtMethod method = new CtMethod(ctReturnType, ms.getName(), ctParameters, _genClass);

        try {
            method.setModifiers(modifiers);
            method.setBody(body);
            method.setExceptionTypes(ctExceptions);

            _genClass.addMethod(method);
        } catch (Exception ex)
        {
            throw new CodeGenerationException(ex);
        }
    }

    public void addConstructor(Class[] parameterTypes, Class[] exceptions, String body)
    {
        CtClass[] ctParameters = convertClasses(parameterTypes);
        CtClass[] ctExceptions = convertClasses(exceptions);

        try
        {
            CtConstructor constructor = new CtConstructor(ctParameters, _genClass);
            constructor.setExceptionTypes(ctExceptions);
            constructor.setBody(body);

            _genClass.addConstructor(constructor);
        } catch (Exception ex) 
        {
            throw new CodeGenerationException(ex);
        }
    }

    public void commit()
    {
    }

    protected CtClass[] convertClasses(Class[] inputClasses)
    {
        if (inputClasses == null || inputClasses.length == 0)
            return null;

        int count = inputClasses.length;
        CtClass[] result = new CtClass[count];

        for (int i = 0; i < count; i++)
        {
            CtClass ctClass = getCtClass(inputClasses[i]);

            result[i] = ctClass;
        }

        return result;
    }

    public byte[] getByteCode()
    {
        try
        {
            return _genClass.toBytecode();
        }
        catch (IOException e)
        {
            throw new CodeGenerationException(e);
        }
        catch (CannotCompileException e)
        {
            throw new CodeGenerationException(e);
        }
    }

}
