/*
 * Copyright 2009 Bas Leijdekkers
 *
 * 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 com.siyeh.ipp.adapter;

import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
import com.siyeh.IntentionPowerPackBundle;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.util.IncorrectOperationException;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;

import java.util.List;
import java.util.ArrayList;

public class AdapterToListenerIntention extends MutablyNamedIntention {

  @NotNull
  @Override
  protected PsiElementPredicate getElementPredicate() {
    return new AdapterToListenerPredicate();
  }

  @Override
  protected String getTextForElement(PsiElement element) {
    final String text = element.getText();
    return IntentionPowerPackBundle.message(
      "adapter.to.listener.intention.name", text);
  }

  @Override
  protected void processIntention(@NotNull PsiElement element)
    throws IncorrectOperationException {
    final PsiElement parent = element.getParent();
    final PsiElement grandParent = parent.getParent();
    if (!(grandParent instanceof PsiClass)) {
      return;
    }
    final PsiClass aClass = (PsiClass)grandParent;
    final PsiReferenceList extendsList = aClass.getExtendsList();
    if (extendsList == null) {
      return;
    }
    final PsiJavaCodeReferenceElement[] extendsReferences =
      extendsList.getReferenceElements();
    if (extendsReferences.length != 1) {
      return;
    }
    final PsiJavaCodeReferenceElement extendsReference =
      extendsReferences[0];
    final PsiElement target = extendsReference.resolve();
    if (!(target instanceof PsiClass)) {
      return;
    }
    final PsiClass extendsClass = (PsiClass)target;
    final PsiReferenceList implementsList =
      extendsClass.getImplementsList();
    if (implementsList == null) {
      return;
    }
    final PsiJavaCodeReferenceElement[] implementsReferences =
      implementsList.getReferenceElements();
    final List<PsiJavaCodeReferenceElement> listenerReferences =
      new ArrayList();
    for (PsiJavaCodeReferenceElement implementsReference :
      implementsReferences) {
      final String name = implementsReference.getReferenceName();
      if (name != null && !name.endsWith("Listener")) {
        continue;
      }
      final PsiElement implementsTarget = implementsReference.resolve();
      if (!(implementsTarget instanceof PsiClass)) {
        continue;
      }
      final PsiClass implementsClass = (PsiClass)implementsTarget;
      if (!implementsClass.isInterface()) {
        continue;
      }
      final PsiMethod[] methods = implementsClass.getMethods();
      for (PsiMethod method : methods) {
        final PsiMethod overridingMethod =
          aClass.findMethodBySignature(method, false);
        if (overridingMethod == null) {
          implementMethodInClass(method, aClass);
          continue;
        }
        final PsiMethod[] superMethods =
          overridingMethod.findSuperMethods(implementsClass);
        for (PsiMethod superMethod : superMethods) {
          if (!superMethod.equals(method)) {
            continue;
          }
          removeCallsToSuperMethodFromMethod(overridingMethod,
                                             extendsClass);
        }
      }
      listenerReferences.add(implementsReference);
    }
    extendsReference.delete();
    final PsiReferenceList referenceList = aClass.getImplementsList();
    if (referenceList != null) {
      for (PsiJavaCodeReferenceElement listenerReference :
        listenerReferences) {
        referenceList.add(listenerReference);
      }
    }
  }

  private static void removeCallsToSuperMethodFromMethod(
    @NotNull PsiMethod overridingMethod,
    @NotNull PsiClass superClass) {
    final PsiCodeBlock body = overridingMethod.getBody();
    if (body == null) {
      return;
    }
    final PsiStatement[] statements = body.getStatements();
    for (PsiStatement statement : statements) {
      if (!(statement instanceof PsiExpressionStatement)) {
        continue;
      }
      final PsiExpressionStatement expressionStatement =
        (PsiExpressionStatement)statement;
      final PsiExpression expression =
        expressionStatement.getExpression();
      if (!(expression instanceof PsiMethodCallExpression)) {
        continue;
      }
      final PsiMethodCallExpression
        methodCallExpression =
        (PsiMethodCallExpression)expression;
      final PsiReferenceExpression methodExpression =
        methodCallExpression.getMethodExpression();
      final PsiExpression qualifier =
        methodExpression.getQualifierExpression();
      if (!(qualifier instanceof PsiSuperExpression)) {
        continue;
      }
      final PsiMethod targetMethod =
        methodCallExpression.resolveMethod();
      if (targetMethod == null) {
        continue;
      }
      final PsiClass containingClass = targetMethod.getContainingClass();
      if (!superClass.equals(containingClass)) {
        continue;
      }
      statement.delete();
    }
  }

  private static void implementMethodInClass(@NotNull PsiMethod method,
                                             @NotNull PsiClass aClass) {
    final PsiMethod newMethod = (PsiMethod)aClass.add(method);
    final PsiDocComment comment = newMethod.getDocComment();
    if (comment != null) {
      comment.delete();
    }
    final PsiModifierList modifierList = newMethod.getModifierList();
    modifierList.setModifierProperty(PsiModifier.ABSTRACT, false);
    final Project project = aClass.getProject();
    final CodeStyleSettings codeStyleSettings =
      CodeStyleSettingsManager.getSettings(project);
    if (codeStyleSettings.INSERT_OVERRIDE_ANNOTATION &&
        PsiUtil.isLanguageLevel6OrHigher(aClass)) {
      modifierList.addAnnotation("java.lang.Override");
    }
    final PsiElementFactory factory =
      JavaPsiFacade.getElementFactory(project);
    final PsiCodeBlock codeBlock = factory.createCodeBlock();
    newMethod.add(codeBlock);
  }
}