package org.codehaus.groovy.classgen;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.codehaus.groovy.ast.ClassCodeVisitorSupport;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.CodeVisitorSupport;
import org.codehaus.groovy.ast.ConstructorNode;
import org.codehaus.groovy.ast.FieldNode;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.Parameter;
import org.codehaus.groovy.ast.expr.ArgumentListExpression;
import org.codehaus.groovy.ast.expr.ArrayExpression;
import org.codehaus.groovy.ast.expr.BinaryExpression;
import org.codehaus.groovy.ast.expr.ClassExpression;
import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.FieldExpression;
import org.codehaus.groovy.ast.expr.ListExpression;
import org.codehaus.groovy.ast.expr.MethodCallExpression;
import org.codehaus.groovy.ast.expr.SpreadExpression;
import org.codehaus.groovy.ast.expr.VariableExpression;
import org.codehaus.groovy.ast.stmt.BlockStatement;
import org.codehaus.groovy.ast.stmt.ExpressionStatement;
import org.codehaus.groovy.ast.stmt.ReturnStatement;
import org.codehaus.groovy.ast.stmt.Statement;
import org.codehaus.groovy.control.CompilationUnit;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.syntax.Token;
import org.codehaus.groovy.syntax.Types;
import org.objectweb.asm.Opcodes;

public class EnumVisitor extends ClassCodeVisitorSupport{

    // some constants for modifiers
    private static final int FS = Opcodes.ACC_FINAL | Opcodes.ACC_STATIC;
    private static final int PS = Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC;
    private static final int PUBLIC_FS = Opcodes.ACC_PUBLIC | FS;
    private static final int PRIVATE_FS = Opcodes.ACC_PRIVATE | FS;
    
    private final CompilationUnit compilationUnit;
    private final SourceUnit sourceUnit;
    
    
    public EnumVisitor(CompilationUnit cu, SourceUnit su) {
        compilationUnit = cu;
        sourceUnit = su;
    }    
    
    public void visitClass(ClassNode node) {
        if (!isEnum(node)) return;
        completeEnum(node);
    }

    protected SourceUnit getSourceUnit() {
        return sourceUnit;
    }
    
    private boolean isEnum(ClassNode node) {
       return (node.getModifiers()&Opcodes.ACC_ENUM) != 0;
    }

    private void completeEnum(final ClassNode enumClass) {
        ClassNode enumArray = enumClass.makeArray();

        // create values field
        FieldNode values = new FieldNode("$VALUES",PRIVATE_FS,enumArray,enumClass,null);
        values.setSynthetic(true);      
        {
            // create values() method
            MethodNode valuesMethod = new MethodNode("values",PUBLIC_FS,enumArray,new Parameter[0],ClassNode.EMPTY_ARRAY,null);
            valuesMethod.setSynthetic(true);
            BlockStatement code = new BlockStatement();
            code.addStatement(
                    new ReturnStatement(
                            new MethodCallExpression(new FieldExpression(values),"clone",MethodCallExpression.NO_ARGUMENTS)
                    )
            );
            valuesMethod.setCode(code);
            enumClass.addMethod(valuesMethod);
        }
        
        {        
            // create valueOf
            Parameter stringParameter = new Parameter(ClassHelper.STRING_TYPE,"name");
            MethodNode valueOfMethod = new MethodNode("valueOf",PS,enumClass,new Parameter[]{stringParameter},ClassNode.EMPTY_ARRAY,null);
            ArgumentListExpression callArguments = new ArgumentListExpression();
            callArguments.addExpression(new ClassExpression(enumClass));
            callArguments.addExpression(new VariableExpression("name"));

            BlockStatement code = new BlockStatement();
            code.addStatement(
                    new ReturnStatement(
                            new MethodCallExpression(new ClassExpression(ClassHelper.Enum_Type),"valueOf",callArguments)
                    )
            );
            valueOfMethod.setCode(code);
            valueOfMethod.setSynthetic(true);
            enumClass.addMethod(valueOfMethod);
        }
        addConstructor(enumClass);
        {
            // constructor helper
            // This method is used instead of calling the constructor as
            // calling the constrcutor may require a table with MetaClass
            // selecting the constructor for each enum value. So instead we
            // use this method to have a central point for constructor selection
            // and only one table. The whole construction is needed because 
            // Reflection forbids access to the enum constructor.
            // code:
            // def $INIT(Object[] para) {
            //  return this(*para)
            // }            
            Parameter[] parameter = new Parameter[]{new Parameter(ClassHelper.OBJECT_TYPE.makeArray(), "para")};
            MethodNode initMethod = new MethodNode("$INIT",PRIVATE_FS,enumClass,parameter,ClassNode.EMPTY_ARRAY,null);
            initMethod.setSynthetic(true);
            ConstructorCallExpression cce = new ConstructorCallExpression(
                    ClassNode.THIS,
                    new ArgumentListExpression(
                            new SpreadExpression(new VariableExpression("para"))
                    )
            );
            BlockStatement code = new BlockStatement();
            code.addStatement(new ReturnStatement(cce));
            initMethod.setCode(code);
            enumClass.addMethod(initMethod);
        }
        
        {
            // static init
            List fields = enumClass.getFields();
            List arrayInit = new ArrayList();
            int value = -1;
            Token assign = Token.newSymbol(Types.ASSIGN, -1, -1);
            List block = new ArrayList();
            for (Iterator iterator = fields.iterator(); iterator.hasNext();) {
                FieldNode field = (FieldNode) iterator.next();
                if ((field.getModifiers()&Opcodes.ACC_ENUM) == 0) continue;
                value++;
                
                ArgumentListExpression args = new ArgumentListExpression();
                args.addExpression(new ConstantExpression(field.getName()));
                args.addExpression(new ConstantExpression(new Integer(value)));
                if (field.getInitialExpression()!=null) {
                    ListExpression oldArgs = (ListExpression) field.getInitialExpression();
                    for (Iterator oldArgsIterator = oldArgs.getExpressions().iterator(); oldArgsIterator.hasNext();) {
                        Expression exp = (Expression) oldArgsIterator.next();
                        args.addExpression(exp);
                    }
                }
                field.setInitialValueExpression(null);
                block.add(
                        new ExpressionStatement(
                                new BinaryExpression(
                                        new FieldExpression(field),
                                        assign,
                                        new MethodCallExpression(new ClassExpression(enumClass),"$INIT",args)
                                )
                        )
                );
                arrayInit.add(new FieldExpression(field));
            }
            
            block.add(
                    new ExpressionStatement(
                            new BinaryExpression(new FieldExpression(values),assign,new ArrayExpression(enumClass,arrayInit))
                    )
            );
            enumClass.addStaticInitializerStatements(block, true);
            enumClass.addField(values);
        }
        
        
    }

    private void addConstructor(ClassNode enumClass) {
        // first look if there are declared constructors
        List ctors = new ArrayList(enumClass.getDeclaredConstructors());
        if (ctors.size()==0) {
            // add default constructor
            ConstructorNode init = new ConstructorNode(Opcodes.ACC_PRIVATE,new Parameter[0],ClassNode.EMPTY_ARRAY,new BlockStatement());
            enumClass.addConstructor(init);
            ctors.add(init);
        } 
        
        // for each constructor:
        // if constructordoes not define a call to super, then transform constructor
        // to get String,int parameters at beginning and add call super(String,int)  
        
        for (Iterator iterator = ctors.iterator(); iterator.hasNext();) {
            ConstructorNode ctor = (ConstructorNode) iterator.next();
            if (ctor.firstStatementIsSpecialConstructorCall()) continue;
            // we need to add parameters
            Parameter[] oldP = ctor.getParameters();
            Parameter[] newP = new Parameter[oldP.length+2];
            String stringParameterName = getUniqueVariableName("__str",ctor.getCode());
            newP[0] = new Parameter(ClassHelper.STRING_TYPE,stringParameterName);
            String intParameterName = getUniqueVariableName("__int",ctor.getCode());
            newP[1] = new Parameter(ClassHelper.int_TYPE,intParameterName);
            System.arraycopy(oldP, 0, newP, 2, oldP.length);
            ctor.setParameters(newP);
            // and a super call
            ConstructorCallExpression cce = new ConstructorCallExpression(
                    ClassNode.SUPER,
                    new ArgumentListExpression(
                           new VariableExpression(stringParameterName),
                           new VariableExpression(intParameterName)
                    )
            );
            BlockStatement code = new BlockStatement();
            code.addStatement(new ExpressionStatement(cce));
            Statement oldCode = ctor.getCode();
            if (oldCode!=null) code.addStatement(oldCode);
            ctor.setCode(code);
        }
    }

    private String getUniqueVariableName(final String name, Statement code) {
        if (code==null) return name;
        final Object[] found=new Object[1];
        CodeVisitorSupport cv = new CodeVisitorSupport() {
            public void visitVariableExpression(VariableExpression expression) {
                if (expression.getName().equals(name)) found[0]=Boolean.TRUE;
            }
        };
        code.visit(cv);
        if (found[0]!=null) return getUniqueVariableName("_"+name, code);
        return name;
    }

}
