/*
 * Copyright (c) 2011 Google Inc.
 *
 * All rights reserved. This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License v1.0 which
 * accompanies this distribution, and is available at
 *
 * http://www.eclipse.org/legal/epl-v10.html
 */
package com.google.eclipse.protobuf.formatting;

import static com.google.eclipse.protobuf.grammar.CommonKeyword.*;
import static com.google.eclipse.protobuf.util.CommonWords.space;

import org.eclipse.xtext.Keyword;
import org.eclipse.xtext.formatting.impl.AbstractDeclarativeFormatter;
import org.eclipse.xtext.formatting.impl.FormattingConfig;

import com.google.eclipse.protobuf.services.*;
import com.google.eclipse.protobuf.services.ProtobufGrammarAccess.EnumElements;
import com.google.eclipse.protobuf.services.ProtobufGrammarAccess.ExtendMessageElements;
import com.google.eclipse.protobuf.services.ProtobufGrammarAccess.GroupElements;
import com.google.eclipse.protobuf.services.ProtobufGrammarAccess.MessageElements;
import com.google.eclipse.protobuf.services.ProtobufGrammarAccess.RpcElements;
import com.google.eclipse.protobuf.services.ProtobufGrammarAccess.ServiceElements;

/**
 * This class provides custom formatting.
 *
 * @see <a href="http://www.eclipse.org/Xtext/documentation/2_0_0/105-formatting.php">Xtext Formatting</a>
 */
public class ProtobufFormatter extends AbstractDeclarativeFormatter {

  @Override protected void configureFormatting(FormattingConfig c) {
    ProtobufGrammarAccess g = (ProtobufGrammarAccess) getGrammarAccess();
    c.setLinewrap(0, 1, 2).before(g.getSL_COMMENTRule());
    c.setLinewrap(1).after(g.getPackageRule());
    c.setLinewrap(1).after(g.getBuiltInOptionRule());
    c.setLinewrap(1).after(g.getImportRule());
    c.setLinewrap(1).after(g.getFieldRule());
    c.setLinewrap(1).after(g.getPropertyRule());
    c.setLinewrap(1).after(g.getEnumRule());
    c.setLinewrap(1).after(g.getEnumElementRule());
    c.setLinewrap(1).after(g.getRpcRule());
    for (Keyword k : g.findKeywords(EQUAL.toString())) {
      c.setSpace(space()).around(k);
    }
    for (Keyword k : g.findKeywords(SEMICOLON.toString())) {
      c.setNoSpace().before(k);
    }
    for (Keyword k : g.findKeywords("{")) {
      c.setLinewrap(1).after(k);
    }
    for (Keyword k : g.findKeywords("}")) {
      c.setLinewrap(2).after(k);
    }
    for (Keyword k : g.findKeywords(OPENING_BRACKET.toString())) {
      c.setNoSpace().after(k);
    }
    for (Keyword k : g.findKeywords(CLOSING_BRACKET.toString())) {
      c.setNoSpace().before(k);
    }
    indentMessageElements(c, g);
    indentExtendMessageElements(c, g);
    indentGroupElements(c, g);
    indentEnumElements(c, g);
    indentServiceElements(c, g);
    indentRpcElements(c, g);
  }

  private void indentMessageElements(FormattingConfig c, ProtobufGrammarAccess g) {
    MessageElements e = g.getMessageAccess();
    c.setIndentationIncrement().after(e.getLeftCurlyBracketKeyword_2());
    c.setIndentationDecrement().before(e.getRightCurlyBracketKeyword_4());
  }

  private void indentExtendMessageElements(FormattingConfig c, ProtobufGrammarAccess g) {
    ExtendMessageElements e = g.getExtendMessageAccess();
    c.setIndentationIncrement().after(e.getLeftCurlyBracketKeyword_2());
    c.setIndentationDecrement().before(e.getRightCurlyBracketKeyword_4());
  }

  private void indentGroupElements(FormattingConfig c, ProtobufGrammarAccess g) {
    GroupElements e = g.getGroupAccess();
    c.setIndentationIncrement().after(e.getLeftCurlyBracketKeyword_6());
    c.setIndentationDecrement().before(e.getRightCurlyBracketKeyword_8());
  }

  private void indentEnumElements(FormattingConfig c, ProtobufGrammarAccess g) {
    EnumElements e = g.getEnumAccess();
    c.setIndentationIncrement().after(e.getLeftCurlyBracketKeyword_2());
    c.setIndentationDecrement().before(e.getRightCurlyBracketKeyword_4());
  }

  private void indentServiceElements(FormattingConfig c, ProtobufGrammarAccess g) {
    ServiceElements e = g.getServiceAccess();
    c.setIndentationIncrement().after(e.getLeftCurlyBracketKeyword_2());
    c.setIndentationDecrement().before(e.getRightCurlyBracketKeyword_4());
  }

  private void indentRpcElements(FormattingConfig c, ProtobufGrammarAccess g) {
    RpcElements e = g.getRpcAccess();
    c.setIndentationIncrement().after(e.getLeftCurlyBracketKeyword_9_0_0_0());
    c.setIndentationDecrement().before(e.getRightCurlyBracketKeyword_9_0_0_2());
  }
}

@@ -682,503 +682,28 @@
 ces.
-*;%0Aimport com.google.eclipse.protobuf.services.ProtobufGrammarAccess.EnumElements;%0Aimport com.google.eclipse.protobuf.services.ProtobufGrammarAccess.ExtendMessageElements;%0Aimport com.google.eclipse.protobuf.services.ProtobufGrammarAccess.GroupElements;%0Aimport com.google.eclipse.protobuf.services.ProtobufGrammarAccess.MessageElements;%0Aimport com.google.eclipse.protobuf.services.ProtobufGrammarAccess.RpcElements;%0Aimport com.google.eclipse.protobuf.services.ProtobufGrammarAccess.ServiceElement
+ProtobufGrammarAcces
 s;%0A%0A
@@ -1758,24 +1758,68 @@
 rds(%22%7B%22)) %7B%0A
+      c.setIndentationIncrement().after(k);%0A
       c.setL
@@ -1885,24 +1885,69 @@
 rds(%22%7D%22)) %7B%0A
+      c.setIndentationDecrement().before(k);%0A
       c.setL
@@ -2180,1910 +2180,14 @@
 k);%0A
+
     %7D%0A
-    indentMessageElements(c, g);%0A    indentExtendMessageElements(c, g);%0A    indentGroupElements(c, g);%0A    indentEnumElements(c, g);%0A    indentServiceElements(c, g);%0A    indentRpcElements(c, g);%0A  %7D%0A%0A  private void indentMessageElements(FormattingConfig c, ProtobufGrammarAccess g) %7B%0A    MessageElements e = g.getMessageAccess();%0A    c.setIndentationIncrement().after(e.getLeftCurlyBracketKeyword_2());%0A    c.setIndentationDecrement().before(e.getRightCurlyBracketKeyword_4());%0A  %7D%0A%0A  private void indentExtendMessageElements(FormattingConfig c, ProtobufGrammarAccess g) %7B%0A    ExtendMessageElements e = g.getExtendMessageAccess();%0A    c.setIndentationIncrement().after(e.getLeftCurlyBracketKeyword_2());%0A    c.setIndentationDecrement().before(e.getRightCurlyBracketKeyword_4());%0A  %7D%0A%0A  private void indentGroupElements(FormattingConfig c, ProtobufGrammarAccess g) %7B%0A    GroupElements e = g.getGroupAccess();%0A    c.setIndentationIncrement().after(e.getLeftCurlyBracketKeyword_6());%0A    c.setIndentationDecrement().before(e.getRightCurlyBracketKeyword_8());%0A  %7D%0A%0A  private void indentEnumElements(FormattingConfig c, ProtobufGrammarAccess g) %7B%0A    EnumElements e = g.getEnumAccess();%0A    c.setIndentationIncrement().after(e.getLeftCurlyBracketKeyword_2());%0A    c.setIndentationDecrement().before(e.getRightCurlyBracketKeyword_4());%0A  %7D%0A%0A  private void indentServiceElements(FormattingConfig c, ProtobufGrammarAccess g) %7B%0A    ServiceElements e = g.getServiceAccess();%0A    c.setIndentationIncrement().after(e.getLeftCurlyBracketKeyword_2());%0A    c.setIndentationDecrement().before(e.getRightCurlyBracketKeyword_4());%0A  %7D%0A%0A  private void indentRpcElements(FormattingConfig c, ProtobufGrammarAccess g) %7B%0A    RpcElements e = g.getRpcAccess();%0A    c.setIndentationIncrement().after(e.getLeftCurlyBracketKeyword_9_0_0_0());%0A    c.setIndentationDecrement().before(e.getRightCurlyBracketKeyword_9_0_0_2());%0A
   %7D%0A

Clean up code.