package com.jetbrains.python.inspections;

import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeInspection.*;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.actions.AddSelfQuickFix;
import com.jetbrains.python.actions.RenameParameterQuickFix;
import com.jetbrains.python.psi.*;
import static com.jetbrains.python.psi.PyFunction.Flag.CLASSMETHOD;
import static com.jetbrains.python.psi.PyFunction.Flag.STATICMETHOD;

import com.jetbrains.python.psi.impl.PyPsiUtils;
import com.jetbrains.python.psi.resolve.PyResolveUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;

import java.util.Set;

/**
 * Looks for the 'self'.
 * User: dcheryasov
 * Date: Nov 17, 2008
 */
public class PyMethodParametersInspection extends LocalInspectionTool {
  @Nls
  @NotNull
  public String getGroupDisplayName() {
    return PyBundle.message("INSP.GROUP.python");
  }

  @Nls
  @NotNull
  public String getDisplayName() {
    return PyBundle.message("INSP.NAME.problematic.first.parameter");
  }

  @NotNull
  public String getShortName() {
    return "PyMethodParametersInspection";
  }

  @Override
  public boolean isEnabledByDefault() {
    return true;
  }

  @NotNull
  public HighlightDisplayLevel getDefaultLevel() {
    return HighlightDisplayLevel.INFO;
  }

  @NotNull
  @Override
  public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
    return new Visitor(holder);
  }

  public static class Visitor extends PyInspectionVisitor {

    public Visitor(final ProblemsHolder holder) {
      super(holder);
    }

    @Override
    public void visitPyFunction(final PyFunction node) {
      PsiElement cap = PyResolveUtil.getConcealingParent(node);
      if (cap instanceof PyClass) {
        PyParameterList plist = node.getParameterList();
        PyParameter[] params = plist.getParameters();
        Set<PyFunction.Flag> flags = PyUtil.detectDecorationsAndWrappersOf(node);
        if (params.length == 0) {
          // check for "staticmetod"
          if (flags.contains(STATICMETHOD) || !PyPsiUtils.isMethodContext(plist)) return; // no params may be fine
          // check actual param list
          ASTNode name_node = node.getNameNode();
          if (name_node != null) {
            PsiElement open_paren = plist.getFirstChild();
            PsiElement close_paren = plist.getLastChild();
            if (
              open_paren != null && close_paren != null &&
              "(".equals(open_paren.getText()) && ")".equals(close_paren.getText())
            ) {
              registerProblem(
                plist, PyBundle.message("INSP.must.have.first.parameter"),
                ProblemHighlightType.GENERIC_ERROR, null, new AddSelfQuickFix()
              );
            }
          }
        }
        else {
          PyNamedParameter first_param = params[0].getAsNamed();
          if (first_param != null) {
            String pname = first_param.getText();
            // every dup, swap, drop, or dup+drop of "self"
            @NonNls String[] mangled = {"eslf", "sself", "elf", "felf", "slef", "seelf", "slf", "sslf", "sefl", "sellf", "sef", "seef"};
            for (String typo : mangled) {
              if (typo.equals(pname)) {
                registerProblem(
                  PyUtil.sure(params[0].getNode()).getPsi(),
                  PyBundle.message("INSP.probably.mistyped.self"),
                  new RenameParameterQuickFix(PyNames.CANONICAL_SELF)
                );
                return;
              }
            }
            // TODO: check for style settings
            if (flags.contains(CLASSMETHOD)) {
              String CLS = "cls";
              if (!CLS.equals(pname)) {
                registerProblem(
                  PyUtil.sure(params[0].getNode()).getPsi(),
                  PyBundle.message("INSP.usually.named.cls"),
                  new RenameParameterQuickFix(CLS)
                );
              }
            }
            else if (!PyNames.CANONICAL_SELF.equals(pname) && ! flags.contains(STATICMETHOD)) {
              registerProblem(
                PyUtil.sure(params[0].getNode()).getPsi(),
                PyBundle.message("INSP.usually.named.self"),
                new RenameParameterQuickFix(PyNames.CANONICAL_SELF)
              );
            }
          }
          else { // the unusual case of a method with first tuple param
            if (! flags.contains(STATICMETHOD)) {
              registerProblem(plist, PyBundle.message("INSP.first.param.must.not.be.tuple"));
            }
          }
        }
      }
    }
  }

}

@@ -611,58 +611,8 @@
 HOD;
-%0A%0Aimport com.jetbrains.python.psi.impl.PyPsiUtils;
 %0Aimp
@@ -2254,46 +2254,8 @@
 HOD)
- %7C%7C !PyPsiUtils.isMethodContext(plist)
 ) re

Revert "PY-520"