/*
 * 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 com.intellij.refactoring.inline;

import com.intellij.codeInsight.ChangeContextUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.patterns.ElementPattern;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.source.codeStyle.CodeEditUtil;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.intellij.patterns.PlatformPatterns.psiElement;
import static com.intellij.patterns.PsiJavaPatterns.psiExpressionStatement;

/**
 * @author yole
*/
class InlineToAnonymousConstructorProcessor {
  private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.inline.InlineToAnonymousConstructorProcessor");

  private static final Key<PsiAssignmentExpression> ourAssignmentKey = Key.create("assignment");
  private static final Key<PsiCallExpression> ourCallKey = Key.create("call");
  public static final ElementPattern ourNullPattern = psiElement(PsiLiteralExpression.class).withText(PsiKeyword.NULL);
  private static final ElementPattern ourAssignmentPattern = psiExpressionStatement().withChild(psiElement(PsiAssignmentExpression.class).save(ourAssignmentKey));
  private static final ElementPattern ourSuperCallPattern = psiExpressionStatement().withFirstChild(
    psiElement(PsiMethodCallExpression.class).save(ourCallKey).withFirstChild(psiElement().withText(PsiKeyword.SUPER)));
  private static final ElementPattern ourThisCallPattern = psiExpressionStatement().withFirstChild(psiElement(PsiMethodCallExpression.class).withFirstChild(
    psiElement().withText(PsiKeyword.THIS)));

  private final PsiClass myClass;
  private PsiNewExpression myNewExpression;
  private final PsiType mySuperType;
  private final Map<String, PsiExpression> myFieldInitializers = new HashMap<String, PsiExpression>();
  private final Map<PsiParameter, PsiVariable> myLocalsForParameters = new HashMap<PsiParameter, PsiVariable>();
  private PsiStatement myNewStatement;
  private final PsiElementFactory myElementFactory;
  private PsiMethod myConstructor;
  private PsiExpressionList myConstructorArguments;
  private PsiParameterList myConstructorParameters;

  public InlineToAnonymousConstructorProcessor(final PsiClass aClass, final PsiNewExpression psiNewExpression,
                                               final PsiType superType) {
    myClass = aClass;
    myNewExpression = psiNewExpression;
    mySuperType = superType;
    myNewStatement = PsiTreeUtil.getParentOfType(myNewExpression, PsiStatement.class);
    myElementFactory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory();
  }

  public void run() throws IncorrectOperationException {
    checkInlineChainingConstructor();
    JavaResolveResult classResolveResult = myNewExpression.getClassReference().advancedResolve(false);
    JavaResolveResult methodResolveResult = myNewExpression.resolveMethodGenerics();
    myConstructor = (PsiMethod) methodResolveResult.getElement();
    myConstructorArguments = myNewExpression.getArgumentList();

    PsiSubstitutor classResolveSubstitutor = classResolveResult.getSubstitutor();
    PsiType substType = classResolveSubstitutor.substitute(mySuperType);

    PsiTypeParameter[] typeParams = myClass.getTypeParameters();
    PsiType[] substitutedParameters = PsiType.createArray(typeParams.length);
    for(int i=0; i< typeParams.length; i++) {
      substitutedParameters [i] = classResolveSubstitutor.substitute(typeParams [i]);
    }

    @NonNls StringBuilder builder = new StringBuilder("new ");
    builder.append(substType.getCanonicalText());
    builder.append("() {}");

    PsiNewExpression superNewExpressionTemplate = (PsiNewExpression) myElementFactory.createExpressionFromText(builder.toString(),
                                                                                                      myNewExpression.getContainingFile());
    PsiClassInitializer initializerBlock = myElementFactory.createClassInitializer();
    PsiVariable outerClassLocal = null;
    if (myNewExpression.getQualifier() != null && myClass.getContainingClass() != null) {
      outerClassLocal = generateOuterClassLocal();
    }
    if (myConstructor != null) {
      myConstructorParameters = myConstructor.getParameterList();

      final PsiExpressionList argumentList = superNewExpressionTemplate.getArgumentList();
      assert argumentList != null;

      if (myNewStatement != null) {
        generateLocalsForArguments();
      }
      analyzeConstructor(initializerBlock.getBody());
      addSuperConstructorArguments(argumentList);
    }

    ChangeContextUtil.encodeContextInfo(myClass.getNavigationElement(), true);
    PsiClass classCopy = (PsiClass) myClass.getNavigationElement().copy();
    ChangeContextUtil.clearContextInfo(myClass);
    final PsiClass anonymousClass = superNewExpressionTemplate.getAnonymousClass();
    assert anonymousClass != null;

    int fieldCount = myClass.getFields().length;
    int processedFields = 0;
    PsiElement token = anonymousClass.getRBrace();
    if (initializerBlock.getBody().getStatements().length > 0 && fieldCount == 0) {
      insertInitializerBefore(initializerBlock, anonymousClass, token);
    }

    for(PsiElement child: classCopy.getChildren()) {
      if ((child instanceof PsiMethod && !((PsiMethod) child).isConstructor()) ||
          child instanceof PsiClassInitializer || child instanceof PsiClass) {
        if (!myFieldInitializers.isEmpty() || !myLocalsForParameters.isEmpty() || classResolveSubstitutor != PsiSubstitutor.EMPTY || outerClassLocal != null) {
          replaceReferences((PsiMember) child, substitutedParameters, outerClassLocal);
        }
        child = anonymousClass.addBefore(child, token);
      }
      else if (child instanceof PsiField) {
        PsiField field = (PsiField) child;
        replaceReferences(field, substitutedParameters, outerClassLocal);
        PsiExpression initializer = myFieldInitializers.get(field.getName());
        field = (PsiField) anonymousClass.addBefore(field, token);
        if (initializer != null) {
          field.setInitializer(initializer);
        }
        processedFields++;
        if (processedFields == fieldCount && initializerBlock.getBody().getStatements().length > 0) {
          insertInitializerBefore(initializerBlock, anonymousClass, token);
        }
      }
    }
    if (PsiTreeUtil.getChildrenOfType(anonymousClass, PsiMember.class) == null) {
      anonymousClass.deleteChildRange(anonymousClass.getLBrace(), anonymousClass.getRBrace());
    }
    PsiNewExpression superNewExpression = (PsiNewExpression) myNewExpression.replace(superNewExpressionTemplate);
    superNewExpression = (PsiNewExpression)ChangeContextUtil.decodeContextInfo(superNewExpression, superNewExpression.getAnonymousClass(), null);
    JavaCodeStyleManager.getInstance(superNewExpression.getProject()).shortenClassReferences(superNewExpression);
  }

  private void insertInitializerBefore(final PsiClassInitializer initializerBlock, final PsiClass anonymousClass, final PsiElement token)
      throws IncorrectOperationException {
    anonymousClass.addBefore(CodeEditUtil.createLineFeed(token.getManager()), token);
    anonymousClass.addBefore(initializerBlock, token);
    anonymousClass.addBefore(CodeEditUtil.createLineFeed(token.getManager()), token);
  }

  private void checkInlineChainingConstructor() {
    while(true) {
      PsiMethod constructor = myNewExpression.resolveConstructor();
      if (constructor == null || !InlineMethodHandler.isChainingConstructor(constructor)) break;
      InlineMethodProcessor.inlineConstructorCall(myNewExpression);
    }
  }

  private void analyzeConstructor(final PsiCodeBlock initializerBlock) throws IncorrectOperationException {
    PsiCodeBlock body = myConstructor.getBody();
    assert body != null;
    for(PsiElement child: body.getChildren()) {
      if (child instanceof PsiStatement) {
        PsiStatement stmt = (PsiStatement) child;
        ProcessingContext context = new ProcessingContext();
        if (ourAssignmentPattern.accepts(stmt, context)) {
          PsiAssignmentExpression expression = context.get(ourAssignmentKey);
          if (processAssignmentInConstructor(expression)) {
            initializerBlock.addBefore(replaceParameterReferences(stmt, null, false), initializerBlock.getRBrace());
          }
        }
        else if (!ourSuperCallPattern.accepts(stmt) && !ourThisCallPattern.accepts(stmt)) {
          replaceParameterReferences(stmt, new ArrayList<PsiReferenceExpression>(), false);
          initializerBlock.addBefore(stmt, initializerBlock.getRBrace());
        }
      }
      else if (child instanceof PsiComment) {
        if (child.getPrevSibling() instanceof PsiWhiteSpace) {
          initializerBlock.addBefore(child.getPrevSibling(), initializerBlock.getRBrace());
        }
        initializerBlock.addBefore(child, initializerBlock.getRBrace());
      }
    }
  }

  private boolean processAssignmentInConstructor(final PsiAssignmentExpression expression) {
    if (expression.getLExpression() instanceof PsiReferenceExpression) {
      PsiReferenceExpression lExpr = (PsiReferenceExpression) expression.getLExpression();
      final PsiExpression rExpr = expression.getRExpression();
      if (rExpr == null) return false;
      final PsiElement psiElement = lExpr.resolve();
      if (psiElement instanceof PsiField) {
        PsiField field = (PsiField) psiElement;
        if (myClass.getManager().areElementsEquivalent(field.getContainingClass(), myClass)) {
          final List<PsiReferenceExpression> localVarRefs = new ArrayList<PsiReferenceExpression>();
          final PsiExpression initializer;
          try {
            initializer = (PsiExpression) replaceParameterReferences(rExpr.copy(), localVarRefs, false);
          }
          catch (IncorrectOperationException e) {
            LOG.error(e);
            return false;
          }
          if (!localVarRefs.isEmpty()) {
            return true;
          }

          myFieldInitializers.put(field.getName(), initializer);
        }
      }
      else if (psiElement instanceof PsiVariable) {
        return true;
      }
    }
    return false;
  }

  public static boolean isConstant(final PsiExpression expr) {
    Object constantValue = JavaPsiFacade.getInstance(expr.getProject()).getConstantEvaluationHelper().computeConstantExpression(expr);
    return constantValue != null || ourNullPattern.accepts(expr);
  }

  private PsiVariable generateOuterClassLocal() {
    PsiClass outerClass = myClass.getContainingClass();
    assert outerClass != null;
    return generateLocal(StringUtil.decapitalize(outerClass.getName()),
                         myElementFactory.createType(outerClass), myNewExpression.getQualifier());
  }

  private PsiVariable generateLocal(final String baseName, final PsiType type, final PsiExpression initializer) {
    final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(myClass.getProject());

    String baseNameForIndex = baseName;
    int index = 0;
    String localName;
    while(true) {
      localName = codeStyleManager.suggestUniqueVariableName(baseNameForIndex, myNewExpression, true);
      if (myClass.findFieldByName(localName, false) == null) {
        break;
      }
      index++;
      baseNameForIndex = baseName + index;
    }
    try {
      final PsiDeclarationStatement declaration = myElementFactory.createVariableDeclarationStatement(localName, type, initializer);
      PsiVariable variable = (PsiVariable)declaration.getDeclaredElements()[0];
      PsiUtil.setModifierProperty(variable, PsiModifier.FINAL, true);
      final PsiElement parent = myNewStatement.getParent();
      if (parent instanceof PsiCodeBlock) {
        variable = (PsiVariable)((PsiDeclarationStatement)parent.addBefore(declaration, myNewStatement)).getDeclaredElements()[0];
      }
      else {
        final int offsetInStatement = myNewExpression.getTextRange().getStartOffset() - myNewStatement.getTextRange().getStartOffset();
        final PsiBlockStatement blockStatement = (PsiBlockStatement)myElementFactory.createStatementFromText("{}", null);
        PsiCodeBlock block = blockStatement.getCodeBlock();
        block.add(declaration);
        block.add(myNewStatement);
        block = ((PsiBlockStatement)myNewStatement.replace(blockStatement)).getCodeBlock();

        variable = (PsiVariable)((PsiDeclarationStatement)block.getStatements()[0]).getDeclaredElements()[0];
        myNewStatement = block.getStatements()[1];
        myNewExpression = PsiTreeUtil.getParentOfType(myNewStatement.findElementAt(offsetInStatement), PsiNewExpression.class);
      }

      return variable;
    }
    catch (IncorrectOperationException e) {
      LOG.error(e);
      return null;
    }
  }

  private void generateLocalsForArguments() {
    PsiExpression[] expressions = myConstructorArguments.getExpressions();
    for (int i = 0; i < expressions.length; i++) {
      PsiExpression expr = expressions[i];
      PsiParameter parameter = myConstructorParameters.getParameters()[i];
      if (parameter.isVarArgs()) {
        PsiEllipsisType ellipsisType = (PsiEllipsisType)parameter.getType();
        PsiType baseType = ellipsisType.getComponentType();
        @NonNls StringBuilder exprBuilder = new StringBuilder("new ");
        exprBuilder.append(baseType.getCanonicalText());
        exprBuilder.append("[] { }");
        try {
          PsiNewExpression newExpr = (PsiNewExpression) myElementFactory.createExpressionFromText(exprBuilder.toString(), myClass);
          PsiArrayInitializerExpression arrayInitializer = newExpr.getArrayInitializer();
          assert arrayInitializer != null;
          for(int j=i; j < expressions.length; j++) {
            arrayInitializer.add(expressions [j]);
          }

          PsiVariable variable = generateLocal(parameter.getName(), ellipsisType.toArrayType(), newExpr);
          myLocalsForParameters.put(parameter, variable);
        }
        catch (IncorrectOperationException e) {
          LOG.error(e);
        }

        break;
      }
      else if (!isConstant(expr)) {
        PsiVariable variable = generateLocal(parameter.getName(), parameter.getType(), expr);
        myLocalsForParameters.put(parameter, variable);
      }
    }
  }

  private void addSuperConstructorArguments(PsiExpressionList argumentList) throws IncorrectOperationException {
    final PsiCodeBlock body = myConstructor.getBody();
    assert body != null;
    PsiStatement[] statements = body.getStatements();
    if (statements.length == 0) {
      return;
    }
    ProcessingContext context = new ProcessingContext();
    if (!ourSuperCallPattern.accepts(statements[0], context)) {
      return;
    }
    PsiExpressionList superArguments = context.get(ourCallKey).getArgumentList();
    if (superArguments != null) {
      for(PsiExpression argument: superArguments.getExpressions()) {
        final PsiElement superArgument = replaceParameterReferences(argument.copy(), new ArrayList<PsiReferenceExpression>(), true);
        argumentList.add(superArgument);
      }
    }
  }

  private PsiElement replaceParameterReferences(PsiElement argument,
                                                @Nullable final List<PsiReferenceExpression> localVarRefs,
                                                final boolean replaceFieldsWithInitializers) throws IncorrectOperationException {
    if (argument instanceof PsiReferenceExpression) {
      PsiElement element = ((PsiReferenceExpression)argument).resolve();
      if (element instanceof PsiParameter) {
        PsiParameter parameter = (PsiParameter)element;
        if (myLocalsForParameters.containsKey(parameter)) {
          return argument.replace(getParameterReference(parameter));
        }
        int index = myConstructorParameters.getParameterIndex(parameter);
        return argument.replace(myConstructorArguments.getExpressions() [index]);
      }
    }

    final List<Pair<PsiReferenceExpression, PsiParameter>> parameterReferences = new ArrayList<Pair<PsiReferenceExpression, PsiParameter>>();
    final Map<PsiElement, PsiElement> elementsToReplace = new HashMap<PsiElement, PsiElement>();
    argument.accept(new JavaRecursiveElementWalkingVisitor() {
      @Override public void visitReferenceExpression(final PsiReferenceExpression expression) {
        super.visitReferenceExpression(expression);
        final PsiElement psiElement = expression.resolve();
        if (psiElement instanceof PsiParameter) {
          parameterReferences.add(Pair.create(expression, (PsiParameter)psiElement));
        }
        else if ((psiElement instanceof PsiField || psiElement instanceof PsiMethod) &&
                 ((PsiMember) psiElement).getContainingClass() == myClass.getSuperClass()) {
          PsiMember member = (PsiMember) psiElement;
          if (member.hasModifierProperty(PsiModifier.STATIC) &&
              expression.getQualifierExpression() == null) {
            final String qualifiedText = myClass.getSuperClass().getQualifiedName() + "." + member.getName();
            try {
              final PsiExpression replacement = myElementFactory.createExpressionFromText(qualifiedText, myClass);
              elementsToReplace.put(expression, replacement); 
            }
            catch (IncorrectOperationException e) {
              LOG.error(e);
            }
          }
        }
        else if (psiElement instanceof PsiVariable) {
          if (localVarRefs != null) {
            localVarRefs.add(expression);
          }
          if (replaceFieldsWithInitializers && psiElement instanceof PsiField && ((PsiField) psiElement).getContainingClass() == myClass) {
            final PsiExpression initializer = ((PsiField)psiElement).getInitializer();
            if (isConstant(initializer)) {
              elementsToReplace.put(expression, initializer);
            }
          }
        }
      }
    });
    for (Pair<PsiReferenceExpression, PsiParameter> pair: parameterReferences) {
      PsiReferenceExpression ref = pair.first;
      PsiParameter param = pair.second;
      if (myLocalsForParameters.containsKey(param)) {
        ref.replace(getParameterReference(param));
      }
      else {
        int index = myConstructorParameters.getParameterIndex(param);
        if (ref == argument) {
          argument = argument.replace(myConstructorArguments.getExpressions() [index]);
        }
        else {
          ref.replace(myConstructorArguments.getExpressions() [index]);
        }
      }
    }
    return RefactoringUtil.replaceElementsWithMap(argument, elementsToReplace);
  }

  private PsiExpression getParameterReference(final PsiParameter parameter) throws IncorrectOperationException {
    PsiVariable variable = myLocalsForParameters.get(parameter);
    return myElementFactory.createExpressionFromText(variable.getName(), myClass);
  }

  private void replaceReferences(final PsiMember method,
                                 final PsiType[] substitutedParameters, final PsiVariable outerClassLocal) throws IncorrectOperationException {
    final Map<PsiElement, PsiElement> elementsToReplace = new HashMap<PsiElement, PsiElement>();
    method.accept(new JavaRecursiveElementWalkingVisitor() {
      @Override public void visitReferenceExpression(final PsiReferenceExpression expression) {
        super.visitReferenceExpression(expression);
        final PsiElement element = expression.resolve();
        if (element instanceof PsiField) {
          try {
            PsiField field = (PsiField)element;
            if (myClass.getContainingClass() != null && field.getContainingClass() == myClass.getContainingClass() &&
                     outerClassLocal != null) {
              PsiReferenceExpression expr = (PsiReferenceExpression)expression.copy();
              PsiExpression qualifier = myElementFactory.createExpressionFromText(outerClassLocal.getName(), field.getContainingClass());
              expr.setQualifierExpression(qualifier);
              elementsToReplace.put(expression, expr);
            }
          }
          catch (IncorrectOperationException e) {
            LOG.error(e);
          }
        }
      }

      @Override public void visitTypeParameter(final PsiTypeParameter classParameter) {
        super.visitTypeParameter(classParameter);
        PsiReferenceList list = classParameter.getExtendsList();
        PsiJavaCodeReferenceElement[] referenceElements = list.getReferenceElements();
        for(PsiJavaCodeReferenceElement reference: referenceElements) {
          PsiElement psiElement = reference.resolve();
          if (psiElement instanceof PsiTypeParameter) {
            checkReplaceTypeParameter(reference, (PsiTypeParameter) psiElement);
          }
        }
      }

      @Override public void visitTypeElement(final PsiTypeElement typeElement) {
        super.visitTypeElement(typeElement);
        if (typeElement.getType() instanceof PsiClassType) {
          PsiClassType classType = (PsiClassType) typeElement.getType();
          PsiClass psiClass = classType.resolve();
          if (psiClass instanceof PsiTypeParameter) {
            checkReplaceTypeParameter(typeElement, (PsiTypeParameter) psiClass);
          }
        }
      }

      private void checkReplaceTypeParameter(PsiElement element, PsiTypeParameter target) {
        PsiClass containingClass = method.getContainingClass();
        PsiTypeParameter[] psiTypeParameters = containingClass.getTypeParameters();
        for(int i=0; i<psiTypeParameters.length; i++) {
          if (psiTypeParameters [i] == target) {
            PsiType substType = substitutedParameters[i];
            if (substType == null) {
              substType = PsiType.getJavaLangObject(element.getManager(), ProjectScope.getAllScope(element.getProject()));
            }
            if (element instanceof PsiJavaCodeReferenceElement) {
              LOG.assertTrue(substType instanceof PsiClassType);
              elementsToReplace.put(element, myElementFactory.createReferenceElementByType((PsiClassType)substType));
            } else {
              elementsToReplace.put(element, myElementFactory.createTypeElement(substType));
            }
          }
        }
      }
    });
    RefactoringUtil.replaceElementsWithMap(method, elementsToReplace);
  }
}