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

import static com.redhat.ceylon.eclipse.code.editor.EditorUtil.getSelection;

import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.ltk.core.refactoring.DocumentChange;
import org.eclipse.text.edits.ReplaceEdit;

import ceylon.file.Writer;
import ceylon.file.Writer$impl;
import ceylon.formatter.format_;

import com.redhat.ceylon.compiler.typechecker.tree.Tree;
import com.redhat.ceylon.eclipse.code.parse.CeylonParseController;

final class FormatAction extends Action {
    private final CeylonEditor editor;

    FormatAction(CeylonEditor editor) {
        super(null);
        this.editor = editor;
    }
    
    @Override
    public void run() {
        IDocument document = editor.getCeylonSourceViewer().getDocument();
        final ITextSelection ts = getSelection(editor);
        CeylonParseController pc = editor.getParseController();
        Tree.CompilationUnit rootNode = pc.getRootNode();
        if (rootNode==null) return;
        
        final StringBuilder builder = new StringBuilder(document.getLength());
        format_.format(rootNode, format_.format$options(rootNode), new Writer() {

            @Override
            public Object write(String string) {
                builder.append(string);
                return null; // void
            }
            
            // the rest is boring
            
            @Override
            public Writer$impl $ceylon$file$Writer$impl() {
                return new Writer$impl(this);
            }
            @Override
            public Object close() {
                return null; // void
            }
            @Override
            public Object destroy(Throwable arg0) {
                return null; // void
            }
            @Override
            public Object flush() {
                return null; // void
            }
            @Override
            public Object writeLine() {
                // unused; ceylon.formatter has its own newline handling
                throw new UnsupportedOperationException();
            }
            @Override
            public Object writeLine(String line) {
                // unused; ceylon.formatter has its own newline handling
                throw new UnsupportedOperationException();
            }
            @Override
            public String writeLine$line() {
                return ""; // default value for "line" parameter
            }
        });
        
        String text = builder.toString();
        try {
            if (!document.get().equals(text)) {
                DocumentChange change = 
                        new DocumentChange("Format", document);
                change.setEdit(new ReplaceEdit(0, document.getLength(), text));
                change.perform(new NullProgressMonitor());
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

}
@@ -119,16 +119,194 @@
 ction;%0A%0A
+import java.util.List;%0A%0Aimport org.antlr.runtime.BufferedTokenStream;%0Aimport org.antlr.runtime.CommonToken;%0Aimport org.antlr.runtime.Token;%0Aimport org.antlr.runtime.TokenSource;%0A
 import o
@@ -350,16 +350,16 @@
 onitor;%0A
-
 import o
@@ -1156,16 +1156,22 @@
         
+final 
 CeylonPa
@@ -1226,16 +1226,22 @@
         
+final 
 Tree.Com
@@ -1310,22 +1310,556 @@
 ==null) 
-return
+%7B%0A            return;%0A        %7D%0A        final TokenSource tokens = new TokenSource() %7B%0A            int i = 0;%0A            List%3CCommonToken%3E tokens = pc.getTokens();%0A            @Override%0A            public Token nextToken() %7B%0A                if (i%3Ctokens.size())%0A                    return tokens.get(i++);%0A                else%0A                    return null;%0A            %7D%0A            @Override%0A            public String getSourceName() %7B%0A                throw new IllegalStateException(%22No one should need this%22);%0A            %7D%0A        %7D
 ;%0A      
@@ -3295,32 +3295,32 @@
 r%0A            %7D%0A
-
         %7D);%0A    
@@ -3312,16 +3312,49 @@
        %7D
+, new BufferedTokenStream(tokens)
 );%0A     

Fix formatter whitespace handling