package com.intellij.codeInsight.daemon.impl.quickfix;

import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.CodeInsightUtil;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.util.IncorrectOperationException;

public class AddVariableInitializerFix implements IntentionAction {
  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.AddReturnFix");
  private final PsiVariable myVariable;

  public AddVariableInitializerFix(PsiVariable variable) {
    myVariable = variable;
  }

  public String getText() {
    return CodeInsightBundle.message("quickfix.add.variable.text", myVariable.getName());
  }

  public String getFamilyName() {
    return CodeInsightBundle.message("quickfix.add.variable.family.name");
  }

  public boolean isAvailable(Project project, Editor editor, PsiFile file) {
    return myVariable != null
        && myVariable.isValid()
        && myVariable.getManager().isInProject(myVariable)
        && !myVariable.hasInitializer()
        ;
  }

  public void invoke(Project project, Editor editor, PsiFile file) {
    if (!CodeInsightUtil.prepareFileForWrite(myVariable.getContainingFile())) return;

    try {
      String initializerText = suggestInitializer();
      PsiElementFactory factory = myVariable.getManager().getElementFactory();
      PsiExpression initializer = factory.createExpressionFromText(initializerText, myVariable);
      if (myVariable instanceof PsiLocalVariable) {
        ((PsiLocalVariable)myVariable).setInitializer(initializer);
      }
      else if (myVariable instanceof PsiField) {
        ((PsiField)myVariable).setInitializer(initializer);
      }
      else {
        LOG.error("Unknown variable type: "+myVariable);
      }
      TextRange range = myVariable.getInitializer().getTextRange();
      int offset = range.getStartOffset();
      editor.getCaretModel().moveToOffset(offset);
      editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
      editor.getSelectionModel().setSelection(range.getEndOffset(), range.getStartOffset());
    }
    catch (IncorrectOperationException e) {
      LOG.error(e);
    }
  }

  private String suggestInitializer() {
    PsiType type = myVariable.getType();
    return PsiTypesUtil.getDefaultValueOfType(type);
  }

  public boolean startInWriteAction() {
    return true;
  }
}

@@ -557,16 +557,58 @@
 ception;
+%0Aimport org.jetbrains.annotations.NotNull;
 %0A%0Apublic
@@ -916,24 +916,35 @@
 iable;%0A  %7D%0A%0A
+  @NotNull%0A
   public Str
@@ -1046,32 +1046,43 @@
 etName());%0A  %7D%0A%0A
+  @NotNull%0A
   public String 
@@ -1208,16 +1208,25 @@
 ailable(
+@NotNull 
 Project 
@@ -1462,16 +1462,25 @@
  invoke(
+@NotNull 
 Project 
@@ -1512,24 +1512,59 @@
 siFile file)
+ throws IncorrectOperationException
  %7B%0A    if (!
@@ -1645,20 +1645,8 @@
 n;%0A%0A
-    try %7B%0A  
     
@@ -1688,26 +1688,24 @@
 tializer();%0A
-  
     PsiEleme
@@ -1773,18 +1773,16 @@
 ();%0A    
- 
- 
 PsiExpre
@@ -1860,26 +1860,24 @@
 yVariable);%0A
-  
     if (myVa
@@ -1916,26 +1916,24 @@
 le) %7B%0A      
-  
 ((PsiLocalVa
@@ -1976,38 +1976,34 @@
 itializer);%0A    
-  %7D%0A  
+%7D%0A
     else if (myV
@@ -2029,26 +2029,24 @@
 PsiField) %7B%0A
-  
       ((PsiF
@@ -2091,30 +2091,26 @@
 lizer);%0A    
-  %7D%0A  
+%7D%0A
     else %7B%0A 
@@ -2108,18 +2108,16 @@
  else %7B%0A
-  
       LO
@@ -2167,18 +2167,16 @@
 e);%0A
-  
     %7D%0A  
     
@@ -2171,16 +2171,84 @@
     %7D%0A  
+  CodeInsightUtil.forcePsiPostprocessAndRestoreElement(myVariable);%0A
     Text
@@ -2309,18 +2309,16 @@
 ();%0A    
- 
- 
 int offs
@@ -2346,18 +2346,16 @@
 fset();%0A
-  
     edit
@@ -2395,26 +2395,24 @@
 ffset);%0A    
- 
- 
 editor.getSc
@@ -2462,18 +2462,16 @@
 ATIVE);%0A
-  
     edit
@@ -2519,11 +2519,13 @@
 .get
-End
+Start
 Offs
@@ -2531,37 +2531,35 @@
 set(), range.get
-Start
+End
 Offset());%0A    %7D
@@ -2557,84 +2557,8 @@
 ));%0A
-    %7D%0A    catch (IncorrectOperationException e) %7B%0A      LOG.error(e);%0A    %7D%0A
   %7D%0A

correct caret position