/*
 * Copyright 2000-2009 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.makeStatic;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.javadoc.PsiDocTag;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.move.MoveInstanceMembersUtil;
import com.intellij.refactoring.util.RefactoringChangeUtil;
import com.intellij.refactoring.util.RefactoringUIUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.refactoring.util.javadoc.MethodJavaDocHelper;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NonNls;

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

/**
 * @author ven
 */
public class MakeClassStaticProcessor extends MakeMethodOrClassStaticProcessor<PsiClass> {
  private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.makeMethodStatic.MakeClassStaticProcessor");
  private List<PsiField> myFieldsToSplit = new ArrayList<PsiField>();

  public MakeClassStaticProcessor(final Project project, final PsiClass aClass, final Settings settings) {
    super(project, aClass, settings);
  }

  protected void changeSelf(final PsiElementFactory factory, final UsageInfo[] usages) throws IncorrectOperationException {
    PsiClass containingClass = myMember.getContainingClass();

    //Add fields
    if (mySettings.isMakeClassParameter()) {
      PsiType type = factory.createType(containingClass, PsiSubstitutor.EMPTY);
      final String classParameterName = mySettings.getClassParameterName();
      final String fieldName = convertToFieldName(classParameterName);
      myMember.add(factory.createField(fieldName, type));
    }

    if (mySettings.isMakeFieldParameters()) {
      List<Settings.FieldParameter> parameters = mySettings.getParameterOrderList();

      for (Settings.FieldParameter fieldParameter : parameters) {
        final PsiType type = fieldParameter.type;
        final PsiField field = factory.createField(convertToFieldName(fieldParameter.name), type);
        myMember.add(field);
      }
    }


    PsiMethod[] constructors = myMember.getConstructors();

    if (constructors.length == 0) {
      final PsiMethod defConstructor = (PsiMethod)myMember.add(factory.createConstructor());
      constructors = new PsiMethod[]{defConstructor};
    }

    boolean generateFinalParams = CodeStyleSettingsManager.getSettings(myProject).GENERATE_FINAL_PARAMETERS;
    for (PsiMethod constructor : constructors) {
      final MethodJavaDocHelper javaDocHelper = new MethodJavaDocHelper(constructor);
      PsiParameterList paramList = constructor.getParameterList();
      PsiElement addParameterAfter = null;
      PsiDocTag anchor = null;

      if (mySettings.isMakeClassParameter()) {
        // Add parameter for object
        PsiType parameterType = factory.createType(containingClass, PsiSubstitutor.EMPTY);
        final String classParameterName = mySettings.getClassParameterName();
        PsiParameter parameter = factory.createParameter(classParameterName, parameterType);
        PsiUtil.setModifierProperty(parameter, PsiModifier.FINAL, makeClassParameterFinal(usages) || generateFinalParams);
        addParameterAfter = paramList.addAfter(parameter, null);
        anchor = javaDocHelper.addParameterAfter(classParameterName, anchor);

        addAssignmentToField(classParameterName, constructor);

      }

      if (mySettings.isMakeFieldParameters()) {
        List<Settings.FieldParameter> parameters = mySettings.getParameterOrderList();

        for (Settings.FieldParameter fieldParameter : parameters) {
          final PsiType fieldParameterType = fieldParameter.field.getType();
          final PsiParameter parameter = factory.createParameter(fieldParameter.name, fieldParameterType);
          PsiUtil.setModifierProperty(parameter, PsiModifier.FINAL,
                                      makeFieldParameterFinal(fieldParameter.field, usages) || generateFinalParams);
          addParameterAfter = paramList.addAfter(parameter, addParameterAfter);
          anchor = javaDocHelper.addParameterAfter(fieldParameter.name, anchor);
          addAssignmentToField(fieldParameter.name, constructor);
        }
        for (UsageInfo usage : usages) {
          if (usage instanceof InternalUsageInfo) {
            final PsiElement element = usage.getElement();
            final PsiElement referencedElement = ((InternalUsageInfo)usage).getReferencedElement();
            if (referencedElement instanceof PsiField && mySettings.getNameForField((PsiField)referencedElement) != null) {
              final PsiField field = PsiTreeUtil.getParentOfType(element, PsiField.class);
              if (field != null) {
                MoveInstanceMembersUtil.moveInitializerToConstructor(factory, constructor, field);
              }
            }
          }
        }
      }
      for (PsiField field : myFieldsToSplit) {
        MoveInstanceMembersUtil.moveInitializerToConstructor(factory, constructor, field);
      }
    }


    setupTypeParameterList();

    // Add static modifier
    final PsiModifierList modifierList = myMember.getModifierList();
    modifierList.setModifierProperty(PsiModifier.STATIC, true);
    modifierList.setModifierProperty(PsiModifier.FINAL, false);
  }

  private void addAssignmentToField(final String parameterName, final PsiMethod constructor) {
    @NonNls String fieldName = convertToFieldName(parameterName);
    final PsiManager manager = PsiManager.getInstance(myProject);
    PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
    final PsiCodeBlock body = constructor.getBody();
    if (body != null) {
      try {
        final PsiReferenceExpression refExpr = (PsiReferenceExpression)factory.createExpressionFromText(fieldName, body);
        if (refExpr.resolve() != null) fieldName = "this." + fieldName;
        PsiStatement statement = factory.createStatementFromText(fieldName + "=" + parameterName + ";", null);
        statement = (PsiStatement)CodeStyleManager.getInstance(manager.getProject()).reformat(statement);
        body.add(statement);
      }
      catch (IncorrectOperationException e) {
        LOG.error(e);
      }
    }
  }

  private String convertToFieldName(final String parameterName) {
    JavaCodeStyleManager manager = JavaCodeStyleManager.getInstance(myProject);
    final String propertyName = manager.variableNameToPropertyName(parameterName, VariableKind.PARAMETER);
    final String fieldName = manager.propertyNameToVariableName(propertyName, VariableKind.FIELD);
    return fieldName;
  }

  protected void changeSelfUsage(final SelfUsageInfo usageInfo) throws IncorrectOperationException {
    PsiElement parent = usageInfo.getElement().getParent();
    LOG.assertTrue(parent instanceof PsiCallExpression); //either this() or new()
    PsiCallExpression call = (PsiCallExpression) parent;
    PsiElementFactory factory = JavaPsiFacade.getInstance(call.getProject()).getElementFactory();
    PsiExpressionList args = call.getArgumentList();
    PsiElement addParameterAfter = null;

    if(mySettings.isMakeClassParameter()) {
      PsiElement arg = factory.createExpressionFromText(convertToFieldName(mySettings.getClassParameterName()), null);
      addParameterAfter = args.addAfter(arg, null);
    }

    if(mySettings.isMakeFieldParameters()) {
      List<Settings.FieldParameter> parameters = mySettings.getParameterOrderList();
      for (Settings.FieldParameter fieldParameter : parameters) {
        PsiElement arg = factory.createExpressionFromText(convertToFieldName(fieldParameter.name), null);
        if (addParameterAfter == null) {
          addParameterAfter = args.addAfter(arg, null);
        }
        else {
          addParameterAfter = args.addAfter(arg, addParameterAfter);
        }
      }
    }
  }

  protected void changeInternalUsage(final InternalUsageInfo usage, final PsiElementFactory factory) throws IncorrectOperationException {
    if (!mySettings.isChangeSignature()) return;

    PsiElement element = usage.getElement();

    if (element instanceof PsiReferenceExpression) {
      PsiReferenceExpression newRef = null;

      if (mySettings.isMakeFieldParameters()) {
        PsiElement resolved = ((PsiReferenceExpression) element).resolve();
        if (resolved instanceof PsiField) {
          String name = mySettings.getNameForField((PsiField)resolved);
          if (name != null) {
            name = convertToFieldName(name);
            if (name != null) {
              newRef = (PsiReferenceExpression) factory.createExpressionFromText(name, null);
            }
          }
        }
      }

      if (newRef == null && mySettings.isMakeClassParameter()) {
        newRef =
        (PsiReferenceExpression) factory.createExpressionFromText(
                convertToFieldName(mySettings.getClassParameterName()) + "." + element.getText(), null);
      }

      if (newRef != null) {
        CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(myProject);
        newRef = (PsiReferenceExpression) codeStyleManager.reformat(newRef);
        element.replace(newRef);
      }
    }
    else if (mySettings.isMakeClassParameter() && (element instanceof PsiThisExpression || element instanceof PsiSuperExpression)) {
      final PsiElement replace =
        element.replace(factory.createExpressionFromText(convertToFieldName(mySettings.getClassParameterName()), null));
      final PsiField field = PsiTreeUtil.getParentOfType(replace, PsiField.class);
      if (field != null) {
        myFieldsToSplit.add(field);
      }
    }
    else if (element instanceof PsiNewExpression && mySettings.isMakeClassParameter()) {
      final PsiNewExpression newExpression = ((PsiNewExpression)element);
      LOG.assertTrue(newExpression.getQualifier() == null);
      final String newText = convertToFieldName(mySettings.getClassParameterName()) + "." + newExpression.getText();
      final PsiExpression expr = factory.createExpressionFromText(newText, null);
      element.replace(expr);
    }
  }

  protected void changeExternalUsage(final UsageInfo usage, final PsiElementFactory factory) throws IncorrectOperationException {
    final PsiElement element = usage.getElement();
    if (!(element instanceof PsiJavaCodeReferenceElement)) return;

    PsiJavaCodeReferenceElement methodRef = (PsiJavaCodeReferenceElement)element;
    PsiElement parent = methodRef.getParent();
    if (parent instanceof PsiAnonymousClass) {
      parent = parent.getParent();
    }
    LOG.assertTrue(parent instanceof PsiCallExpression, "call expression expected, found " + parent);

    PsiCallExpression call = (PsiCallExpression)parent;

    PsiExpression instanceRef;

    instanceRef = call instanceof PsiMethodCallExpression ? ((PsiMethodCallExpression)call).getMethodExpression().getQualifierExpression() :
                  ((PsiNewExpression)call).getQualifier();
    PsiElement newQualifier;

    if (instanceRef == null || instanceRef instanceof PsiSuperExpression) {
      final PsiClass thisClass = RefactoringChangeUtil.getThisClass(element);
      @NonNls String thisText;
      if (thisClass.getManager().areElementsEquivalent(thisClass, myMember.getContainingClass())) {
        thisText = "this";
      }
      else {
        thisText = myMember.getContainingClass().getName() + ".this";
      }
      instanceRef = factory.createExpressionFromText(thisText, null);
      newQualifier = null;
    }
    else {
      newQualifier = factory.createReferenceExpression(myMember.getContainingClass());
    }

    if (mySettings.getNewParametersNumber() > 1) {
      int copyingSafetyLevel = RefactoringUtil.verifySafeCopyExpression(instanceRef);
      if (copyingSafetyLevel == RefactoringUtil.EXPR_COPY_PROHIBITED) {
        String tempVar = RefactoringUtil.createTempVar(instanceRef, call, true);
        instanceRef = factory.createExpressionFromText(tempVar, null);
      }
    }


    PsiElement anchor = null;
    PsiExpressionList argList = call.getArgumentList();
    PsiExpression[] exprs = argList.getExpressions();
    if (mySettings.isMakeClassParameter()) {
      if (exprs.length > 0) {
        anchor = argList.addBefore(instanceRef, exprs[0]);
      }
      else {
        anchor = argList.add(instanceRef);
      }
    }


    if (mySettings.isMakeFieldParameters()) {
      List<Settings.FieldParameter> parameters = mySettings.getParameterOrderList();

      for (Settings.FieldParameter fieldParameter : parameters) {
        PsiReferenceExpression fieldRef;
        final String fieldName = fieldParameter.field.getName();
        if (newQualifier != null) {
          fieldRef = (PsiReferenceExpression)factory.createExpressionFromText(
            "a." + fieldName, null);
          fieldRef.getQualifierExpression().replace(instanceRef);
        }
        else {
          fieldRef = (PsiReferenceExpression)factory.createExpressionFromText(fieldName, null);
        }

        if (anchor != null) {
          anchor = argList.addAfter(fieldRef, anchor);
        }
        else {
          if (exprs.length > 0) {
            anchor = argList.addBefore(fieldRef, exprs[0]);
          }
          else {
            anchor = argList.add(fieldRef);
          }
        }
      }
    }

    if (newQualifier != null) {
      if (call instanceof PsiMethodCallExpression) {
        instanceRef.replace(newQualifier);
      } else {
        final PsiAnonymousClass anonymousClass = ((PsiNewExpression)call).getAnonymousClass();
        if (anonymousClass != null) {
          ((PsiNewExpression)call).getQualifier().delete();
          final PsiJavaCodeReferenceElement baseClassReference = anonymousClass.getBaseClassReference();
          baseClassReference.replace(((PsiNewExpression)factory.createExpressionFromText("new " + newQualifier.getText() + "." + baseClassReference.getText() + "()", baseClassReference)).getClassReference());
        } else {
          PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)call).getClassReference();
          LOG.assertTrue(classReference != null);
          final PsiNewExpression newExpr =
            (PsiNewExpression)factory.createExpressionFromText("new " + newQualifier.getText() + "." + classReference.getText() + "()", classReference);
          final PsiExpressionList callArgs = call.getArgumentList();
          if (callArgs != null) {
            final PsiExpressionList argumentList = newExpr.getArgumentList();
            LOG.assertTrue(argumentList != null);
            argumentList.replace(callArgs);
          }
          call.replace(newExpr);
        }
      }
    }
  }

  protected MultiMap<PsiElement,String> getConflictDescriptions(final UsageInfo[] usages) {
    final MultiMap<PsiElement, String> conflicts = super.getConflictDescriptions(usages);

    //Check fields already exist
    if (mySettings.isMakeClassParameter()) {
      final String fieldName = convertToFieldName(mySettings.getClassParameterName());
      final PsiField existing = myMember.findFieldByName(fieldName, false);
      if (existing != null) {
        String message = RefactoringBundle.message("there.is.already.a.0.in.1", RefactoringUIUtil.getDescription(existing, false),
                                              RefactoringUIUtil.getDescription(myMember, false));
              conflicts.putValue(existing, message);
      }
    }

    if (mySettings.isMakeFieldParameters()) {
      final List<Settings.FieldParameter> parameterOrderList = mySettings.getParameterOrderList();
      for (Settings.FieldParameter parameter : parameterOrderList) {
        final String fieldName = convertToFieldName(parameter.name);
        final PsiField existing = myMember.findFieldByName(fieldName, false);

        if (existing != null) {
          String message = RefactoringBundle.message("there.is.already.a.0.in.1", RefactoringUIUtil.getDescription(existing, false),
                                                RefactoringUIUtil.getDescription(myMember, false));
          conflicts.putValue(existing, message);
        }
      }
    }

    return conflicts;
  }

  protected void findExternalUsages(final ArrayList<UsageInfo> result) {
    PsiMethod[] constructors = myMember.getConstructors();
    if (constructors.length > 0) {
      for (PsiMethod constructor : constructors) {
        findExternalReferences(constructor, result);
      }
    } else {
      findDefaultConstructorReferences(result);
    }
  }

  private void findDefaultConstructorReferences(final ArrayList<UsageInfo> result) {
    for (PsiReference ref : ReferencesSearch.search(myMember)) {
      PsiElement element = ref.getElement();
      if (element.getParent() instanceof PsiNewExpression) {
        PsiNewExpression newExpression = (PsiNewExpression)element.getParent();
        PsiElement qualifier = newExpression.getQualifier();
        if (qualifier instanceof PsiThisExpression) qualifier = null;
        if (!PsiTreeUtil.isAncestor(myMember, element, true) || qualifier != null) {
          result.add(new UsageInfo(element));
        } else {
          result.add(new InternalUsageInfo(element, myMember));
        }
      }
    }
  }
}
