/*
 * Copyright 2000-2007 JetBrains s.r.o.
 * 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.jetbrains.plugins.groovy.lang.psi.impl.synthetic;

import com.intellij.lang.Language;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.impl.light.LightMethod;
import com.intellij.psi.util.MethodSignature;
import com.intellij.psi.util.MethodSignatureUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.GroovyFileType;

import java.util.LinkedHashSet;

/**
 * @author ven
 */
public class DefaultGroovyMethod extends LightMethod {
  private PsiMethod myMethod;

  private LightParameterList myParameterList = null;

  private LightModifierList myModifierList;

  @NotNull
  public Language getLanguage() {
    return GroovyFileType.GROOVY_FILE_TYPE.getLanguage();
  }

  public boolean isValid() {
    return true;
  }

  public DefaultGroovyMethod(PsiMethod method, boolean isStatic) {
    super(method.getManager(), method, null);
    myMethod = method;
    final PsiManager manager = method.getManager();
    LinkedHashSet<String> modifiers = new LinkedHashSet<String>();
    modifiers.add(PsiModifier.PUBLIC);
    if (isStatic) modifiers.add(PsiModifier.STATIC);
    myModifierList = new LightModifierList(manager, modifiers);

    final PsiParameter[] originalParameters = method.getParameterList().getParameters();
    final String[] parmNames = new String[originalParameters.length - 1];
    for (int i = 1; i < originalParameters.length; i++) {
      PsiParameter originalParameter = originalParameters[i];
      String baseName;
      final PsiType type = originalParameter.getType();
      String[] nameSuggestions = getManager().getCodeStyleManager().suggestVariableName(VariableKind.PARAMETER, null,
          null, type).names;
      if (nameSuggestions.length > 0) {
        baseName = nameSuggestions[0];
      } else {
        baseName = "p";
      }

      int postfix = 1;

      String name = baseName;
      NextName:
      do {
        for (int j = 1; j < i; j++) {
          if (name.equals(parmNames[j - 1])) {
            name = baseName + postfix;
            postfix++;
            continue NextName;
          }
        }

        break;
      } while (true);

      parmNames[i - 1] = name;
    }

    myParameterList = new LightParameterList(manager, new Computable<LightParameter[]>() {
      public LightParameter[] compute() {
        LightParameter[] result = new LightParameter[parmNames.length];
        for (int i = 0; i < result.length; i++) {
          result[i] = new LightParameter(manager, parmNames[i], null, originalParameters[i+1].getType(), DefaultGroovyMethod.this);

        }
        return result;
      }
    });
  }

  @NotNull
  public MethodSignature getSignature(@NotNull PsiSubstitutor substitutor) {
    final PsiParameter[] parameters = getParameterList().getParameters();
    PsiType[] parameterTypes = new PsiType[parameters.length];
    for (int i = 0; i < parameterTypes.length; i++) {
      parameterTypes[i] = parameters[i].getType();
    }
    return MethodSignatureUtil.createMethodSignature(getName(), parameterTypes, PsiTypeParameter.EMPTY_ARRAY, substitutor); //todo
  }

  @NotNull
  public PsiParameterList getParameterList() {
    return myParameterList;
  }

  @NotNull
  public PsiModifierList getModifierList() {
    return myModifierList;
  }

  public boolean hasModifierProperty(String name) {
    return myModifierList.hasModifierProperty(name);
  }

  public boolean canNavigate() {
    return myMethod.canNavigate();
  }

  public void navigate(boolean requestFocus) {
    myMethod.navigate(requestFocus);
  }
}

@@ -4123,32 +4123,126 @@
 avigate();%0A  %7D%0A%0A
+  public PsiElement getNavigationElement() %7B%0A    return myMethod.getNavigationElement();%0A  %7D%0A%0A
   public void na

correct navigation to DGM