/*
 * Copyright 2000-2013 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 com.intellij.refactoring.encapsulateFields;

import com.intellij.lang.findUsages.DescriptiveNameUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.*;
import com.intellij.refactoring.BaseRefactoringProcessor;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.listeners.RefactoringEventData;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.refactoring.util.DocCommentPolicy;
import com.intellij.refactoring.util.RefactoringUIUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewDescriptor;
import com.intellij.usageView.UsageViewUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

public class EncapsulateFieldsProcessor extends BaseRefactoringProcessor {
  private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.encapsulateFields.EncapsulateFieldsProcessor");

  private PsiClass myClass;
  @NotNull
  private final EncapsulateFieldsDescriptor myDescriptor;
  private final FieldDescriptor[] myFieldDescriptors;

  private HashMap<String,PsiMethod> myNameToGetter;
  private HashMap<String,PsiMethod> myNameToSetter;

  public EncapsulateFieldsProcessor(Project project, @NotNull EncapsulateFieldsDescriptor descriptor) {
    super(project);
    myDescriptor = descriptor;
    myFieldDescriptors = descriptor.getSelectedFields();
    myClass = descriptor.getTargetClass();
  }

  public static void setNewFieldVisibility(PsiField field, EncapsulateFieldsDescriptor descriptor) {
    try {
      if (descriptor.getFieldsVisibility() != null) {
        field.normalizeDeclaration();
        PsiUtil.setModifierProperty(field, descriptor.getFieldsVisibility(), true);
      }
    }
    catch (IncorrectOperationException e) {
      LOG.error(e);
    }
  }

  @Nullable
  @Override
  protected String getRefactoringId() {
    return "refactoring.encapsulateFields";
  }

  @Nullable
  @Override
  protected RefactoringEventData getBeforeData() {
    RefactoringEventData data = new RefactoringEventData();
    final List<PsiElement> fields = new ArrayList<PsiElement>();
    for (FieldDescriptor fieldDescriptor : myFieldDescriptors) {
      fields.add(fieldDescriptor.getField());
    }
    data.addElements(fields);
    return data;
  }

  @Nullable
  @Override
  protected RefactoringEventData getAfterData(UsageInfo[] usages) {
    RefactoringEventData data = new RefactoringEventData();
    List<PsiElement> elements = new ArrayList<PsiElement>();
    if (myNameToGetter != null) {
      elements.addAll(myNameToGetter.values());
    }
    if (myNameToSetter != null) {
      elements.addAll(myNameToSetter.values());
    }
    data.addElements(elements);
    return data;
  }

  @NotNull
  protected UsageViewDescriptor createUsageViewDescriptor(UsageInfo[] usages) {
    FieldDescriptor[] fields = new FieldDescriptor[myFieldDescriptors.length];
    System.arraycopy(myFieldDescriptors, 0, fields, 0, myFieldDescriptors.length);
    return new EncapsulateFieldsViewDescriptor(fields);
  }

  protected String getCommandName() {
    return RefactoringBundle.message("encapsulate.fields.command.name", DescriptiveNameUtil.getDescriptiveName(myClass));
  }

  protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) {
    final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();

    checkExistingMethods(conflicts, true);
    checkExistingMethods(conflicts, false);
    final Collection<PsiClass> classes = ClassInheritorsSearch.search(myClass).findAll();
    for (FieldDescriptor fieldDescriptor : myFieldDescriptors) {
      final Set<PsiMethod> setters = new HashSet<PsiMethod>();
      final Set<PsiMethod> getters = new HashSet<PsiMethod>();

      for (PsiClass aClass : classes) {
        final PsiMethod getterOverrider =
          myDescriptor.isToEncapsulateGet() ? aClass.findMethodBySignature(fieldDescriptor.getGetterPrototype(), false) : null;
        if (getterOverrider != null) {
          getters.add(getterOverrider);
        }
        final PsiMethod setterOverrider =
          myDescriptor.isToEncapsulateSet() ? aClass.findMethodBySignature(fieldDescriptor.getSetterPrototype(), false) : null;
        if (setterOverrider != null) {
          setters.add(setterOverrider);
        }
      }
      if (!getters.isEmpty() || !setters.isEmpty()) {
        final PsiField field = fieldDescriptor.getField();
        for (PsiReference reference : ReferencesSearch.search(field)) {
          final PsiElement place = reference.getElement();
          LOG.assertTrue(place instanceof PsiReferenceExpression);
          final PsiExpression qualifierExpression = ((PsiReferenceExpression)place).getQualifierExpression();
          final PsiClass ancestor;
          if (qualifierExpression == null) {
            ancestor = PsiTreeUtil.getParentOfType(place, PsiClass.class, false);
          }
          else {
            ancestor = PsiUtil.resolveClassInType(qualifierExpression.getType());
          }

          final boolean isGetter = !PsiUtil.isAccessedForWriting((PsiExpression)place);
          for (PsiMethod overridden : isGetter ? getters : setters) {
            if (InheritanceUtil.isInheritorOrSelf(myClass, ancestor, true)) {
              conflicts.putValue(overridden, "There is already a " +
                                             RefactoringUIUtil.getDescription(overridden, true) +
                                             " which would hide generated " +
                                             (isGetter ? "getter" : "setter") + " for " + place.getText());
              break;
            }
          }
        }
      }
    }
    return showConflicts(conflicts, refUsages.get());
  }

  private void checkExistingMethods(MultiMap<PsiElement, String> conflicts, boolean isGetter) {
    if (isGetter) {
      if (!myDescriptor.isToEncapsulateGet()) return;
    }
    else {
      if (!myDescriptor.isToEncapsulateSet()) return;
    }

    for (FieldDescriptor descriptor : myFieldDescriptors) {
      PsiMethod prototype = isGetter
                            ? descriptor.getGetterPrototype()
                            : descriptor.getSetterPrototype();

      final PsiType prototypeReturnType = prototype.getReturnType();
      PsiMethod existing = myClass.findMethodBySignature(prototype, true);
      if (existing != null) {
        final PsiType returnType = existing.getReturnType();
        if (!RefactoringUtil.equivalentTypes(prototypeReturnType, returnType, myClass.getManager())) {
          final String descr = PsiFormatUtil.formatMethod(existing,
                                                          PsiSubstitutor.EMPTY,
                                                          PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS | PsiFormatUtilBase.SHOW_TYPE,
                                                          PsiFormatUtilBase.SHOW_TYPE
          );
          String message = isGetter ?
                           RefactoringBundle.message("encapsulate.fields.getter.exists", CommonRefactoringUtil.htmlEmphasize(descr),
                                                CommonRefactoringUtil.htmlEmphasize(prototype.getName())) :
                           RefactoringBundle.message("encapsulate.fields.setter.exists", CommonRefactoringUtil.htmlEmphasize(descr),
                                                CommonRefactoringUtil.htmlEmphasize(prototype.getName()));
          conflicts.putValue(existing, message);
        }
      } else {
        PsiClass containingClass = myClass.getContainingClass();
        while (containingClass != null && existing == null) {
          existing = containingClass.findMethodBySignature(prototype, true);
          if (existing != null) {
            for (PsiReference reference : ReferencesSearch.search(existing)) {
              final PsiElement place = reference.getElement();
              LOG.assertTrue(place instanceof PsiReferenceExpression);
              final PsiExpression qualifierExpression = ((PsiReferenceExpression)place).getQualifierExpression();
              final PsiClass inheritor;
              if (qualifierExpression == null) {
                inheritor = PsiTreeUtil.getParentOfType(place, PsiClass.class, false);
              } else {
                inheritor = PsiUtil.resolveClassInType(qualifierExpression.getType());
              }

              if (InheritanceUtil.isInheritorOrSelf(inheritor, myClass, true)) {
                conflicts.putValue(existing, "There is already a " + RefactoringUIUtil.getDescription(existing, true) + " which would be hidden by generated " + (isGetter ? "getter" : "setter"));
                break;
              }
            }
          }
          containingClass = containingClass.getContainingClass();
        }
      }
    }
  }

  @NotNull protected UsageInfo[] findUsages() {
    ArrayList<EncapsulateFieldUsageInfo> array = ContainerUtil.newArrayList();
    for (FieldDescriptor fieldDescriptor : myFieldDescriptors) {
      for (final PsiReference reference : ReferencesSearch.search(fieldDescriptor.getField())) {
        final PsiElement element = reference.getElement();
        if (element == null) continue;

        final EncapsulateFieldHelper helper = EncapsulateFieldHelper.getHelper(element.getLanguage());
        if (helper != null) {
          EncapsulateFieldUsageInfo usageInfo = helper.createUsage(myDescriptor, fieldDescriptor, reference);
          if (usageInfo != null) {
            array.add(usageInfo);
          }
        }
      }
    }
    EncapsulateFieldUsageInfo[] usageInfos = array.toArray(new EncapsulateFieldUsageInfo[array.size()]);
    return UsageViewUtil.removeDuplicatedUsages(usageInfos);
  }

  protected void refreshElements(PsiElement[] elements) {
    LOG.assertTrue(elements.length == myFieldDescriptors.length);

    for (int idx = 0; idx < elements.length; idx++) {
      PsiElement element = elements[idx];

      LOG.assertTrue(element instanceof PsiField);

      myFieldDescriptors[idx].refreshField((PsiField)element);
    }

    myClass = myFieldDescriptors[0].getField().getContainingClass();
  }

  protected void performRefactoring(UsageInfo[] usages) {
    updateFieldVisibility();
    generateAccessors();
    processUsagesPerFile(usages);
  }

  private void updateFieldVisibility() {
    if (myDescriptor.getFieldsVisibility() == null) return;

    for (FieldDescriptor descriptor : myFieldDescriptors) {
      setNewFieldVisibility(descriptor.getField(), myDescriptor);
    }
  }

  private void generateAccessors() {
    // generate accessors
    myNameToGetter = new HashMap<String, PsiMethod>();
    myNameToSetter = new HashMap<String, PsiMethod>();

    for (FieldDescriptor fieldDescriptor : myFieldDescriptors) {
      final DocCommentPolicy<PsiDocComment> commentPolicy = new DocCommentPolicy<PsiDocComment>(myDescriptor.getJavadocPolicy());

      PsiField field = fieldDescriptor.getField();
      final PsiDocComment docComment = field.getDocComment();
      if (myDescriptor.isToEncapsulateGet()) {
        final PsiMethod prototype = fieldDescriptor.getGetterPrototype();
        assert prototype != null;
        final PsiMethod getter = addOrChangeAccessor(prototype, myNameToGetter);
        if (docComment != null) {
          final PsiDocComment getterJavadoc = (PsiDocComment)getter.addBefore(docComment, getter.getFirstChild());
          commentPolicy.processNewJavaDoc(getterJavadoc);
        }
      }
      if (myDescriptor.isToEncapsulateSet() && !field.hasModifierProperty(PsiModifier.FINAL)) {
        PsiMethod prototype = fieldDescriptor.getSetterPrototype();
        assert prototype != null;
        addOrChangeAccessor(prototype, myNameToSetter);
      }

      if (docComment != null) {
        commentPolicy.processOldJavaDoc(docComment);
      }
    }
  }

  private void processUsagesPerFile(UsageInfo[] usages) {
    Map<PsiFile, List<EncapsulateFieldUsageInfo>> usagesInFiles = new HashMap<PsiFile, List<EncapsulateFieldUsageInfo>>();
    for (UsageInfo usage : usages) {
      PsiElement element = usage.getElement();
      if (element == null) continue;
      final PsiFile file = element.getContainingFile();
      List<EncapsulateFieldUsageInfo> usagesInFile = usagesInFiles.get(file);
      if (usagesInFile == null) {
        usagesInFile = new ArrayList<EncapsulateFieldUsageInfo>();
        usagesInFiles.put(file, usagesInFile);
      }
      usagesInFile.add(((EncapsulateFieldUsageInfo)usage));
    }

    for (List<EncapsulateFieldUsageInfo> usageInfos : usagesInFiles.values()) {
      //this is to avoid elements to become invalid as a result of processUsage
      final EncapsulateFieldUsageInfo[] infos = usageInfos.toArray(new EncapsulateFieldUsageInfo[usageInfos.size()]);
      CommonRefactoringUtil.sortDepthFirstRightLeftOrder(infos);

      for (EncapsulateFieldUsageInfo info : infos) {
        EncapsulateFieldHelper helper = EncapsulateFieldHelper.getHelper(info.getElement().getLanguage());
        helper.processUsage(info,
                            myDescriptor,
                            myNameToSetter.get(info.getFieldDescriptor().getSetterName()),
                            myNameToGetter.get(info.getFieldDescriptor().getGetterName())
        );
      }
    }
  }

  private PsiMethod addOrChangeAccessor(PsiMethod prototype, HashMap<String,PsiMethod> nameToAncestor) {
    PsiMethod existing = myClass.findMethodBySignature(prototype, false);
    PsiMethod result = existing;
    try{
      if (existing == null){
        PsiUtil.setModifierProperty(prototype, myDescriptor.getAccessorsVisibility(), true);
        result = (PsiMethod) myClass.add(prototype);
      }
      else{
        //TODO : change visibility
      }
      nameToAncestor.put(prototype.getName(), result);
      return result;
    }
    catch(IncorrectOperationException e){
      LOG.error(e);
    }
    return null;
  }
}
