/*
 * Copyright 2000-2014 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.refactoring.introduce.field;

import com.intellij.codeInsight.TestFrameworks;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Condition;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.codeStyle.GrReferenceAdjuster;
import org.jetbrains.plugins.groovy.lang.psi.GrQualifiedReference;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrEnumTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstantList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMembersDeclaration;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase;
import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo;

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

/**
 * @author Max Medvedev
 */
public class GrIntroduceFieldProcessor {
  private static final Logger LOG = Logger.getInstance(GrIntroduceFieldProcessor.class);

  private final GrIntroduceContext myContext;
  private final GrIntroduceFieldSettings mySettings;

  @Nullable private GrExpression myInitializer;
  @Nullable private GrVariable myLocalVariable;

  public GrIntroduceFieldProcessor(@NotNull GrIntroduceContext context,
                                   @NotNull GrIntroduceFieldSettings settings) {
    this.myContext = context;
    this.mySettings = settings;
  }

  @Nullable
  public GrVariable run() {
    PsiElement scope = myContext.getScope();
    final PsiClass targetClass = scope instanceof GroovyFileBase ? ((GroovyFileBase)scope).getScriptClass() : (PsiClass)scope;
    if (targetClass == null) return null;

    final GrVariableDeclaration declaration = insertField(targetClass);
    final GrVariable field = declaration.getVariables()[0];

    if (mySettings.removeLocalVar()) {
      myLocalVariable = GrIntroduceHandlerBase.resolveLocalVar(myContext);
      assert myLocalVariable != null : myContext.getExpression() + ", " + myContext.getVar() + ", " + myContext.getStringPart();
    }
    myInitializer = (GrExpression)getInitializer().copy();

    List<PsiElement> replaced = processOccurrences(targetClass, field);

    switch (mySettings.initializeIn()) {
      case CUR_METHOD:
        initializeInMethod(field, replaced);
        break;
      case FIELD_DECLARATION:
        field.setInitializerGroovy(myInitializer);
        break;
      case CONSTRUCTOR:
        initializeInConstructor(field);
        break;
      case SETUP_METHOD:
        initializeInSetup(field);
        break;
    }

    JavaCodeStyleManager.getInstance(declaration.getProject()).shortenClassReferences(declaration);

    if (mySettings.removeLocalVar()) {
      GrIntroduceHandlerBase.deleteLocalVar(myLocalVariable);
    }

    return field;
  }

  @NotNull
  private List<PsiElement> processOccurrences(@NotNull PsiClass targetClass, @NotNull GrVariable field) {
    if (myContext.getStringPart() != null) {
      final GrExpression expr = myContext.getStringPart().replaceLiteralWithConcatenation(field.getName());
      final PsiElement occurrence = replaceOccurrence(field, expr, targetClass);
      updateCaretPosition(occurrence);
      return Collections.singletonList(occurrence);
    }

    if (mySettings.replaceAllOccurrences()) {
      GroovyRefactoringUtil.sortOccurrences(myContext.getOccurrences());
      ArrayList<PsiElement> result = ContainerUtil.newArrayList();
      for (PsiElement occurrence : myContext.getOccurrences()) {
        result.add(replaceOccurrence(field, occurrence, targetClass));
      }
      return result;
    }

    GrVariable var = myContext.getVar();
    if (var != null) {
      GrExpression initializer = var.getInitializerGroovy();
      if (initializer != null) {
        return Collections.singletonList(replaceOccurrence(field, initializer, targetClass));
      }
      else {
        return Collections.emptyList();
      }
    }

    final GrExpression expression = myContext.getExpression();
    assert expression != null;
    if (PsiUtil.isExpressionStatement(expression)) {
      return Collections.<PsiElement>singletonList(expression);
    }
    else {
      return Collections.singletonList(replaceOccurrence(field, expression, targetClass));
    }
  }

  private void updateCaretPosition(@NotNull PsiElement occurrence) {
    myContext.getEditor().getCaretModel().moveToOffset(occurrence.getTextRange().getEndOffset());
    myContext.getEditor().getSelectionModel().removeSelection();
  }

  @NotNull
  protected GrVariableDeclaration insertField(@NotNull PsiClass targetClass) {
    GrVariableDeclaration declaration = createField(targetClass);
    if (targetClass instanceof GrEnumTypeDefinition) {
      final GrEnumConstantList enumConstants = ((GrEnumTypeDefinition)targetClass).getEnumConstantList();
      return (GrVariableDeclaration)targetClass.addAfter(declaration, enumConstants);
    }

    if (targetClass instanceof GrTypeDefinition) {
      PsiElement anchor = getAnchorForDeclaration((GrTypeDefinition)targetClass);
      return (GrVariableDeclaration)targetClass.addAfter(declaration, anchor);
    }

    else {
      assert targetClass instanceof GroovyScriptClass;
      final GroovyFile file = ((GroovyScriptClass)targetClass).getContainingFile();
      PsiElement[] elements = file.getMethods();
      if (elements.length == 0) elements = file.getStatements();
      final PsiElement anchor = ArrayUtil.getFirstElement(elements);
      return (GrVariableDeclaration)file.addBefore(declaration, anchor);
    }
  }

  @Nullable
  private static PsiElement getAnchorForDeclaration(@NotNull GrTypeDefinition targetClass) {
    PsiElement anchor = targetClass.getBody().getLBrace();

    final GrMembersDeclaration[] declarations = targetClass.getMemberDeclarations();
    for (GrMembersDeclaration declaration : declarations) {
      if (declaration instanceof GrVariableDeclaration) anchor = declaration;
      if (!(declaration instanceof GrVariableDeclaration)) return anchor;
    }

    return anchor;
  }

  void initializeInSetup(@NotNull GrVariable field) {
    final PsiMethod setUpMethod = TestFrameworks.getInstance().findOrCreateSetUpMethod(((PsiClass)myContext.getScope()));
    assert setUpMethod instanceof GrMethod;

    final GrOpenBlock body = ((GrMethod)setUpMethod).getBlock();
    final PsiElement anchor = findAnchorForAssignment(body);
    generateAssignment(field, (GrStatement)anchor, body, null);
  }

  void initializeInMethod(@NotNull GrVariable field, @NotNull List<PsiElement> replaced) {
    final PsiElement _scope = myContext.getScope();
    final PsiElement scope = _scope instanceof GroovyScriptClass ? ((GroovyScriptClass)_scope).getContainingFile() : _scope;

    final PsiElement place = replaced.get(0);

    final GrMember member = GrIntroduceFieldHandler.getContainer(place, scope);
    GrStatementOwner container = member instanceof GrMethod ? ((GrMethod)member).getBlock() :
                                 member instanceof GrClassInitializer ? ((GrClassInitializer)member).getBlock() :
                                 place.getContainingFile() instanceof GroovyFile ? ((GroovyFile)place.getContainingFile()) :
                                 null;
    assert container != null;

    final PsiElement anchor;
    if (mySettings.removeLocalVar()) {
      GrVariable variable = myLocalVariable;
      anchor = PsiTreeUtil.getParentOfType(variable, GrStatement.class);
    }
    else {
      anchor = GrIntroduceHandlerBase.findAnchor(replaced.toArray(new PsiElement[replaced.size()]), container);
      GrIntroduceHandlerBase.assertStatement(anchor, myContext.getScope());
    }

    PsiElement occurrence = replaced.get(0);
    if (!mySettings.replaceAllOccurrences() && !isRefToField(occurrence, field) && PsiUtil.isExpressionStatement(occurrence)) {
      generateAssignment(field, (GrStatement)anchor, container, occurrence);
    }
    else {
      generateAssignment(field, (GrStatement)anchor, container, null);
    }
  }

  private static boolean isRefToField(@NotNull PsiElement occurrence, @NotNull PsiElement field) {
    return occurrence instanceof GrReferenceExpression && ((GrReferenceExpression)occurrence).resolve() == field;
  }


  void initializeInConstructor(@NotNull GrVariable field) {
    final PsiClass scope = (PsiClass)myContext.getScope();

    if (scope instanceof GrAnonymousClassDefinition) {
      initializeInAnonymousClassInitializer(field, (GrAnonymousClassDefinition)scope);
    }
    else {
      initializeInConstructor(field, scope);
    }
  }

  private void initializeInConstructor(@NotNull GrVariable field, @NotNull PsiClass scope) {
    PsiMethod[] constructors = scope.getConstructors();
    if (constructors.length == 0) {
      constructors = new PsiMethod[]{generateConstructor(scope)};
    }

    for (PsiMethod constructor : constructors) {
      final GrConstructorInvocation invocation = PsiImplUtil.getChainingConstructorInvocation((GrMethod)constructor);
      if (invocation != null && invocation.isThisCall()) continue;
      final PsiElement anchor = findAnchorForAssignment(((GrMethod)constructor).getBlock());

      generateAssignment(field, (GrStatement)anchor, ((GrMethod)constructor).getBlock(), null);
    }
  }

  @NotNull
  private PsiMethod generateConstructor(@NotNull PsiClass scope) {
    final String name = scope.getName();
    LOG.assertTrue(name != null, scope.getText());
    GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(myContext.getProject());
    final GrMethod
      constructor = factory.createConstructorFromText(name, ArrayUtil.EMPTY_STRING_ARRAY, ArrayUtil.EMPTY_STRING_ARRAY, "{}", scope);
    if (scope instanceof GroovyScriptClass) constructor.getModifierList().setModifierProperty(GrModifier.DEF, true);
    return (PsiMethod)scope.add(constructor);
  }

  private void initializeInAnonymousClassInitializer(@NotNull GrVariable field, @NotNull GrAnonymousClassDefinition scope) {
    final GrClassInitializer[] initializers = scope.getInitializers();
    GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(myContext.getProject());
    final GrClassInitializer initializer = initializers.length == 0 ? (GrClassInitializer)scope.add(factory.createClassInitializer())
                                                                    : initializers[0];

    final PsiElement anchor = findAnchorForAssignment(initializer.getBlock());
    generateAssignment(field, (GrStatement)anchor, initializer.getBlock(), null);
  }

  private void generateAssignment(@NotNull GrVariable field,
                                  @Nullable GrStatement anchor,
                                  @NotNull GrStatementOwner defaultContainer,
                                  @Nullable PsiElement occurrenceToDelete) {
    if (myInitializer == null) return;

    GrAssignmentExpression init = (GrAssignmentExpression)GroovyPsiElementFactory.getInstance(myContext.getProject())
      .createExpressionFromText(mySettings.getName() + " = " + myInitializer.getText());

    GrStatementOwner block;
    if (anchor != null) {
      anchor = GroovyRefactoringUtil.addBlockIntoParent(anchor);
      LOG.assertTrue(anchor.getParent() instanceof GrStatementOwner);
      block = (GrStatementOwner)anchor.getParent();
    }
    else {
      block = defaultContainer;
    }

    init = (GrAssignmentExpression)block.addStatementBefore(init, anchor);
    replaceOccurrence(field, init.getLValue(), (PsiClass)myContext.getScope());

    if (occurrenceToDelete != null) {
      occurrenceToDelete.delete();
    }
  }

  @Nullable
  private GrExpression extractVarInitializer() {
    assert myLocalVariable != null;
    return myLocalVariable.getInitializerGroovy();
  }

  @Nullable
  private PsiElement findAnchorForAssignment(final GrCodeBlock block) {
    final List<PsiElement> elements = ContainerUtil.findAll(myContext.getOccurrences(), new Condition<PsiElement>() {
      @Override
      public boolean value(PsiElement element) {
        return PsiTreeUtil.isAncestor(block, element, true);
      }
    });
    if (elements.isEmpty()) return null;
    return GrIntroduceHandlerBase.findAnchor(ContainerUtil.toArray(elements, new PsiElement[elements.size()]), block);
  }

  @NotNull
  private PsiElement replaceOccurrence(@NotNull GrVariable field, @NotNull PsiElement occurrence, @NotNull PsiClass containingClass) {
    boolean isOriginal = occurrence == myContext.getExpression();
    final GrReferenceExpression newExpr = createRefExpression(field, occurrence, containingClass);
    final PsiElement replaced;
    if (occurrence instanceof GrExpression) {
      replaced = ((GrExpression)occurrence).replaceWithExpression(newExpr, false);
    }
    else {
      replaced = occurrence.replace(newExpr);
    }

    if (replaced instanceof GrQualifiedReference<?>) {
      GrReferenceAdjuster.shortenReference((GrQualifiedReference<?>)replaced);
    }
    if (isOriginal) {
      updateCaretPosition(replaced);
    }
    return replaced;
  }

  @NotNull
  private static GrReferenceExpression createRefExpression(@NotNull GrVariable field,
                                                           @NotNull PsiElement place,
                                                           @NotNull PsiClass containingClass) {
    final String qname = containingClass.getQualifiedName();
    final String prefix = qname != null ? qname + "." : "";
    final String refText;
    if (field.hasModifierProperty(PsiModifier.STATIC)) {
      refText = prefix + field.getName();
    }
    else {
      refText = prefix + "this." + field.getName();
    }

    return GroovyPsiElementFactory.getInstance(place.getProject()).createReferenceExpressionFromText(refText, place);
  }

  @NotNull
  private GrVariableDeclaration createField(@NotNull PsiClass targetClass) {
    final String name = mySettings.getName();
    final PsiType type = mySettings.getSelectedType();
    final String modifier = mySettings.getVisibilityModifier();

    List<String> modifiers = new ArrayList<String>();
    if (targetClass instanceof GroovyScriptClass) {
      modifiers.add("@" + GroovyCommonClassNames.GROOVY_TRANSFORM_FIELD);
    }
    if (mySettings.isStatic()) modifiers.add(PsiModifier.STATIC);
    if (!PsiModifier.PACKAGE_LOCAL.equals(modifier)) modifiers.add(modifier);
    if (mySettings.declareFinal()) modifiers.add(PsiModifier.FINAL);

    final String[] arr_modifiers = ArrayUtil.toStringArray(modifiers);
    final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(myContext.getProject());
    if (targetClass instanceof GroovyScriptClass) {
      return factory.createVariableDeclaration(arr_modifiers, ((GrExpression)null), type, name);
    }
    else {
      return factory.createFieldDeclaration(arr_modifiers, name, null, type);
    }
  }

  @Nullable
  protected GrExpression getInitializer() {
    if (mySettings.removeLocalVar()) {
      return extractVarInitializer();
    }

    GrExpression expression = myContext.getExpression();
    StringPartInfo stringPart = myContext.getStringPart();
    if (expression != null) {
      return expression;
    }
    else if (stringPart != null) {
      return stringPart.createLiteralFromSelected();
    }

    throw new IncorrectOperationException("cannot be here!");
  }
}
