package com.redhat.ceylon.eclipse.code.correct;

import static com.redhat.ceylon.eclipse.util.EditorUtil.getDocument;
import static com.redhat.ceylon.eclipse.util.Indents.getDefaultLineDelimiter;
import static com.redhat.ceylon.eclipse.util.Indents.getIndent;
import static com.redhat.ceylon.eclipse.util.Nodes.findStatement;
import static com.redhat.ceylon.eclipse.util.Nodes.getIdentifyingNode;
import static com.redhat.ceylon.eclipse.util.Nodes.nameProposals;

import java.util.Collection;

import org.eclipse.core.resources.IFile;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.ltk.core.refactoring.TextChange;
import org.eclipse.ltk.core.refactoring.TextFileChange;
import org.eclipse.text.edits.InsertEdit;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;

import com.redhat.ceylon.compiler.typechecker.tree.Node;
import com.redhat.ceylon.compiler.typechecker.tree.Tree;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.BaseMemberExpression;
import com.redhat.ceylon.eclipse.util.FindReferencesVisitor;
import com.redhat.ceylon.eclipse.util.Nodes;
import com.redhat.ceylon.model.typechecker.model.Declaration;
import com.redhat.ceylon.model.typechecker.model.Value;

class ShadowReferenceProposal extends CorrectionProposal {
    
    ShadowReferenceProposal(int offset, int length, TextChange change) {
        super("Shadow reference inside control structure", change,
                new Region(offset, length));
    }
    
    static void addShadowSwitchReferenceProposal(IFile file, 
            Node node, Tree.CompilationUnit rootNode, 
            Collection<ICompletionProposal> proposals) {
        if (node instanceof Tree.Term) {
            Tree.Statement statement = 
                    findStatement(rootNode, node);
            if (statement instanceof Tree.SwitchStatement) {
                String name = nameProposals(node)[0];
                TextFileChange change = 
                        new TextFileChange("Shadow Reference", file);
                change.setEdit(new MultiTextEdit());
                Integer offset = statement.getStartIndex();
                change.addEdit(new ReplaceEdit(offset, 
                        node.getStartIndex()-offset,
                        "value " + name + " = "));
                IDocument doc = getDocument(change);
                change.addEdit(new InsertEdit(node.getEndIndex(), 
                        ";" + 
                        getDefaultLineDelimiter(doc) + 
                        getIndent(statement, doc) +
                        "switch (" + name));
                if (node instanceof BaseMemberExpression) {
                    Tree.BaseMemberExpression bme = 
                            (BaseMemberExpression) node;
                    Declaration d = bme.getDeclaration();
                    if (d!=null) {
                        FindReferencesVisitor frv = 
                                new FindReferencesVisitor(d);
                        Tree.SwitchStatement ss = 
                                (Tree.SwitchStatement) statement;
                        frv.visit(ss.getSwitchCaseList());
                        for (Node n: frv.getNodes()) {
                            Node identifyingNode = 
                                    getIdentifyingNode(n);
                            Integer start = 
                                    identifyingNode.getStartIndex();
                            if (start!=node.getStartIndex()) {
                                int len = identifyingNode.getText().length();
                                change.addEdit(new ReplaceEdit(start, len, name));
                            }
                        }
                    }
                }
                proposals.add(new ShadowReferenceProposal(
                        offset+6, name.length(), change));
            }
        }
    }
    
    static void addShadowReferenceProposal(IFile file, 
            Node node, Tree.CompilationUnit rootNode, 
            Collection<ICompletionProposal> proposals) {
        if (node instanceof Tree.Variable) {
            Tree.Variable var = (Tree.Variable) node;
            int offset = 
                    var.getIdentifier()
                        .getStartIndex();
            Tree.Term term = 
                    var.getSpecifierExpression()
                        .getExpression()
                        .getTerm();
			String name = nameProposals(term)[0];
            TextChange change = 
                    new TextFileChange("Shadow Reference", file);
            change.setEdit(new MultiTextEdit());
            change.addEdit(new InsertEdit(offset, name + " = "));
            Tree.Statement statement = 
                    Nodes.findStatement(rootNode, node);
            Value dec = var.getDeclarationModel();
            FindReferencesVisitor frv = 
            		new FindReferencesVisitor(dec);
            frv.visit(statement);
            for (Node n: frv.getNodes()) {
                Node identifyingNode = getIdentifyingNode(n);
                Integer start = 
                        identifyingNode.getStartIndex();
                if (start!=offset) {
                    int len = identifyingNode.getText().length();
                    change.addEdit(new ReplaceEdit(start, len, name));
                }
            }
            proposals.add(new ShadowReferenceProposal(
                    offset, 1, change));
        }
        else if (node instanceof Tree.Term) {
            String name = nameProposals(node)[0];
            TextChange change = 
                    new TextFileChange("Shadow Reference", file);
//            change.setEdit(new MultiTextEdit());
            Integer offset = node.getStartIndex();
            change.setEdit(new InsertEdit(offset, name + " = "));
            proposals.add(new ShadowReferenceProposal(
                    offset, 1, change));
        }
    }
}
@@ -46,219 +46,8 @@
 t;%0A%0A
-import static com.redhat.ceylon.eclipse.util.EditorUtil.getDocument;%0Aimport static com.redhat.ceylon.eclipse.util.Indents.getDefaultLineDelimiter;%0Aimport static com.redhat.ceylon.eclipse.util.Indents.getIndent;%0A
 impo
@@ -104,24 +104,24 @@
 dStatement;%0A
+
 import stati
@@ -321,49 +321,8 @@
 le;%0A
-import org.eclipse.jface.text.IDocument;%0A
 impo
@@ -1913,32 +1913,34 @@
 ltiTextEdit());%0A
+//
                 
@@ -1975,32 +1975,34 @@
 etStartIndex();%0A
+//
                 
@@ -2041,16 +2041,18 @@
 ffset, %0A
+//
         
@@ -2096,16 +2096,18 @@
 offset,%0A
+//
         
@@ -2141,32 +2141,34 @@
 name + %22 = %22));%0A
+//
                 
@@ -2200,24 +2200,26 @@
 nt(change);%0A
+//
             
@@ -2273,16 +2273,18 @@
 dex(), %0A
+//
         
@@ -2302,24 +2302,26 @@
      %22;%22 + %0A
+//
             
@@ -2364,16 +2364,18 @@
 doc) + %0A
+//
         
@@ -2418,16 +2418,18 @@
  doc) +%0A
+//
         
@@ -2457,32 +2457,248 @@
 ch (%22 + name));%0A
+                Tree.SwitchStatement ss = %0A                        (Tree.SwitchStatement) statement;%0A                int loc = node.getStartIndex();%0A                change.addEdit(new InsertEdit(loc, name + %22 = %22));%0A
                 
@@ -3063,125 +3063,8 @@
 d);%0A
-                        Tree.SwitchStatement ss = %0A                                (Tree.SwitchStatement) statement;%0A
     
@@ -3437,36 +3437,19 @@
 (start!=
-node.getStartIndex()
+loc
 ) %7B%0A    
@@ -3788,16 +3788,11 @@
     
-offset+6
+loc
 , na
@@ -5380,33 +5380,45 @@
         offset, 
-1
+name.length()
 , change));%0A    
@@ -5873,9 +5873,21 @@
 et, 
-1
+name.length()
 , ch

fix #1499 and also use more modern syntax for shadow reference in switch