/*
 * Copyright Red Hat Inc. and/or its affiliates and other contributors
 * as indicated by the authors tag. All rights reserved.
 *
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU General Public License version 2.
 * 
 * This particular file is subject to the "Classpath" exception as provided in the 
 * LICENSE file that accompanied this code.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT A
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License,
 * along with this distribution; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA  02110-1301, USA.
 */

package com.redhat.ceylon.eclipse.core.model.loader.mirror;

import java.util.Map;

import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;

import com.redhat.ceylon.compiler.java.metadata.Name;
import com.redhat.ceylon.compiler.loader.mirror.AnnotationMirror;
import com.redhat.ceylon.compiler.loader.mirror.MethodMirror;
import com.redhat.ceylon.compiler.loader.mirror.TypeMirror;
import com.redhat.ceylon.compiler.loader.mirror.VariableMirror;

public class JDTVariable implements VariableMirror {

    private TypeBinding typeBinding;
    private AnnotationBinding[] annotationBindings;
    private Map<String, AnnotationMirror> annotations;
    private TypeMirror type;
    private MethodMirror methodMirror;
    private String name;

    public JDTVariable(TypeBinding typeBinding, AnnotationBinding[] annotationBindings, MethodMirror methodMirror) {
        this.typeBinding = typeBinding;
        this.annotationBindings = annotationBindings;
        this.methodMirror = methodMirror;
        setName();
    }

    @Override
    public AnnotationMirror getAnnotation(String type) {
        if (annotations == null) {
            annotations = JDTUtils.getAnnotations(annotationBindings);
        }
        return annotations.get(type);
    }

    @Override
    public TypeMirror getType() {
        if (type == null) {
            type = new JDTType(typeBinding);
        }
        return type; 
    }

    @Override
    public String getName() {
        if (name == null) {
            setName();
        }
        return name;
    }
    
    private void setName() {
        AnnotationMirror nameAnnotation = getAnnotation(Name.class.getName());
        if(nameAnnotation != null) {
            name = (String) nameAnnotation.getValue();
            return;
        }
        
        String baseName = toParameterName(typeBinding);
        int count = 0;
        String nameToReturn = baseName;
        for (VariableMirror parameter : methodMirror.getParameters()) {
            if (parameter.getName().equals(nameToReturn)) {
                count ++;
                nameToReturn = baseName + Integer.toString(count);
            }
        }
        name = nameToReturn;
    }
    
    private String toParameterName(TypeBinding parameterType) {
        return new String(parameterType.sourceName())
                .replaceAll("\\.", "_")
                .replaceAll("\\$", "_")
                .replaceAll("\\[\\]", "s").toLowerCase();
    }
}

@@ -998,21 +998,103 @@
 ort 
-java.util.Map
+static java.lang.Character.toLowerCase;%0A%0Aimport java.util.Map;%0Aimport java.util.StringTokenizer
 ;%0A%0Ai
@@ -3347,22 +3347,33 @@
         
-return
+String typeName =
  new Str
@@ -3403,16 +3403,17 @@
 eName())
+;
 %0A       
@@ -3417,39 +3417,71 @@
     
-        .replaceAll(%22%5C%5C.%22, %22_
+StringTokenizer tokens = new StringTokenizer(typeName, %22$.%5B%5D
 %22)
+;
 %0A   
@@ -3489,39 +3489,111 @@
     
-        .replaceAll(%22%5C%5C$%22, %22_%22)
+String result = null;%0A        while (tokens.hasMoreTokens()) %7B%0A            result = tokens.nextToken();
 %0A   
@@ -3597,24 +3597,26 @@
         
+%7D%0A
         
 .replace
@@ -3611,47 +3611,170 @@
     
-.replaceAll(%22%5C%5C%5B%5C%5C%5D%22, %22s%22).toLowerCase(
+if (typeName.endsWith(%22%5B%5D%22)) %7B%0A            result = result + %22Array%22;%0A        %7D%0A        return toLowerCase(result.charAt(0)) + %0A                result.substring(1
 );%0A 

improve parameter name computation