/*
 * generated by Xtext 2.12.0
 */
package org.etsi.mts.tdl.formatting2

import com.google.inject.Inject
import org.eclipse.xtext.formatting2.AbstractFormatter2
import org.eclipse.xtext.formatting2.IFormattableDocument
import org.etsi.mts.tdl.AlternativeBehaviour
import org.etsi.mts.tdl.Annotation
import org.etsi.mts.tdl.Block
import org.etsi.mts.tdl.Comment
import org.etsi.mts.tdl.ComponentInstance
import org.etsi.mts.tdl.CompoundBehaviour
import org.etsi.mts.tdl.Connection
import org.etsi.mts.tdl.Element
import org.etsi.mts.tdl.ElementImport
import org.etsi.mts.tdl.Package
import org.etsi.mts.tdl.PackageableElement
import org.etsi.mts.tdl.TestConfiguration
import org.etsi.mts.tdl.TestDescription
import org.etsi.mts.tdl.services.TDLan2GrammarAccess
import org.etsi.mts.tdl.Message
import org.etsi.mts.tdl.Target
import org.etsi.mts.tdl.BoundedLoopBehaviour
import org.etsi.mts.tdl.UnboundedLoopBehaviour
import org.etsi.mts.tdl.PeriodicBehaviour
import org.etsi.mts.tdl.SingleCombinedBehaviour
import org.etsi.mts.tdl.MultipleCombinedBehaviour
import org.etsi.mts.tdl.ExceptionalBehaviour
import org.etsi.mts.tdl.DataUse
import org.etsi.mts.tdl.ParameterBinding
import org.etsi.mts.tdl.DataInstanceUse
import org.etsi.mts.tdl.StructuredDataType
import org.etsi.mts.tdl.EnumDataType

class TDLan2Formatter extends AbstractFormatter2 {
	
	@Inject extension TDLan2GrammarAccess

	def dispatch void format(Package _package, extension IFormattableDocument document) {
		// TODO: format HiddenRegions around keywords, attributes, cross references, etc. 

	    interior(
       		_package.regionFor.keyword('{').append[newLine],
        	_package.regionFor.keyword('}').prepend[newLine],
        	[indent]
    	)

		for (ElementImport elementImport : _package.getImport()) {
			elementImport.format;
		}
		for (PackageableElement packageableElement : _package.getPackagedElement()) {
			packageableElement.prepend[newLine]
			packageableElement.format;
		}
		for (Package __package : _package.getNestedPackage()) {
			__package.format;
		}
		for (Comment comment : _package.getComment()) {
			comment.format;
		}
		for (Annotation _annotation : _package.getAnnotation()) {
			_annotation.format;
		}
	}
	
	def dispatch void format(PackageableElement p, extension IFormattableDocument document) {
	    p.prepend[newLine]
        p.allRegionsFor.keyword(';').prepend[noSpace]
	    p.allRegionsFor.keyword(';').append[newLine]
	    p.allRegionsFor.keyword(',').prepend[noSpace]
	    p.append[newLine]
	    

        if (p instanceof StructuredDataType) {
//            interior(p, [indent]) 
            if (!p.member.empty) {
                interior(
                    p.regionFor.keyword('(').append[newLine],
                    p.regionFor.keyword(')').prepend[newLine],
                    [indent]
                )
            }  
            for (m : p.member) {
                m.prepend[newLine]
                m.format
            }          
        } else if (p instanceof EnumDataType) {
            interior(
                p.regionFor.keyword('{').append[newLine],
                p.regionFor.keyword('}').prepend[newLine],
                [indent]
            )
            for (v : p.value) {
                v.prepend[newLine]
                v.allRegionsFor.keyword(';').prepend[noSpace]
            }
        } else {
    	    interior(
           		p.regionFor.keyword('{').append[newLine],
            	p.regionFor.keyword('}').prepend[newLine],
            	[indent]
        	)
        } 
        for (Comment comment : p.getComment()) {
            comment.surround[newLine]
            comment.surround[indent]
            comment.format;
        }
        for (Annotation a : p.getAnnotation()) {
            a.surround[newLine]
            a.surround[indent]
            a.format;
        }

	}

	def dispatch void format(TestConfiguration e, extension IFormattableDocument document) {
	    interior(
       		e.regionFor.keyword('{').append[newLine],
        	e.regionFor.keyword('}').prepend[newLine],
        	[indent]
    	)
		for (i : e.componentInstance) {
			i.format	
		}
		for (c : e.connection) {
			c.format
		}
        for (Comment comment : e.getComment()) {
            //comment.prepend[space = "  "]
            comment.regionFor.keyword('Note').append[noSpace]
            //comment.regionFor.keyword('Note').append[space = "  "]
            comment.surround[newLine; indent]
            comment.format;
        }
	}

	def dispatch void format(ComponentInstance e, extension IFormattableDocument document) {
		e.regionFor.keyword(';').append[newLine]
	}

	def dispatch void format(Connection e, extension IFormattableDocument document) {
		e.regionFor.keyword(';').append[newLine]
		for (g : e.endPoint) {
			g.regionFor.keyword('.').prepend[noSpace].append[noSpace]
		}
	}
	
	def dispatch void format(TestDescription e, extension IFormattableDocument document) {
	    interior(
       		e.regionFor.keyword('{').append[newLine],
        	e.regionFor.keyword('}').prepend[newLine].append[newLine],
        	[indent]
    	)
    	e.regionFor.keyword('uses').prepend[newLine].surround[indent]
    	if (!e.testObjective.empty) {
    	    e.testConfiguration.append[newLine]
        	e.regionFor.keyword('test').prepend[newLine].surround[indent]
    	}
    	if (e.behaviourDescription !== null) {
    		e.behaviourDescription.behaviour.format
    	}

		for (c : e.getComment()) {
			c.format
		}
		for (a : e.getAnnotation()) {
			a.format
		}

	}

	def dispatch void format(CompoundBehaviour e, extension IFormattableDocument document) {
	    interior(
       		e.regionFor.keyword('{').append[newLine],
        	e.regionFor.keyword('}').prepend[newLine],
        	[indent]
    	)
		e.block.format

		for (c : e.getComment()) {
			c.format;
		}
		for (a : e.getAnnotation()) {
			a.format
		}
	}

	def dispatch void format(Message e, extension IFormattableDocument document) {
	    interior(
       		e.regionFor.keyword('{').append[newLine],
        	e.regionFor.keyword('}').prepend[newLine],
        	[indent]
    	)
		for (t : e.target) {
			t.format
		}

		e.argument.format

		for (c : e.getComment()) {
			c.format;
		}
		for (a : e.getAnnotation()) {
			a.format
		}
	}

	def dispatch void format(DataUse e, extension IFormattableDocument document) {
	    interior(
       		e.regionFor.keyword('(').append[newLine],
        	e.regionFor.keyword(')').prepend[newLine],
        	[indent]
    	)
		for (t : e.argument) {
			t.format
		}

		for (c : e.getComment()) {
			c.format;
		}
		for (a : e.getAnnotation()) {
			a.format
		}
	}

	def dispatch void format(ParameterBinding e, extension IFormattableDocument document) {
	    interior(
       		e.regionFor.keyword('(').append[newLine],
        	e.regionFor.keyword(')').prepend[newLine],
        	[indent]
    	)
    	e.prepend[newLine]
	}
	
	def dispatch void format(Target e, extension IFormattableDocument document) {
	    interior(
       		e.regionFor.keyword('{').append[newLine],
        	e.regionFor.keyword('}').prepend[newLine],
        	[indent]
    	)

		for (c : e.getComment()) {
			c.format;
		}
		for (a : e.getAnnotation()) {
			a.format
		}
	}


	def dispatch void format(AlternativeBehaviour e, extension IFormattableDocument document) {
	    interior(
       		e.regionFor.keyword('{').append[newLine],
        	e.regionFor.keyword('}').prepend[newLine],
        	[indent]
    	)

		for (b : e.block) {
			b.format
		}

		for (c : e.getComment()) {
			c.format;
		}
		for (a : e.getAnnotation()) {
			a.format
		}
	}

	def dispatch void format(BoundedLoopBehaviour e, extension IFormattableDocument document) {
	    interior(
       		e.regionFor.keyword('{').append[newLine],
        	e.regionFor.keyword('}').prepend[newLine],
        	[indent]
    	)

		e.block.format

		for (c : e.getComment()) {
			c.format;
		}
		for (a : e.getAnnotation()) {
			a.format
		}
	}

	def dispatch void format(SingleCombinedBehaviour e, extension IFormattableDocument document) {
	    interior(
       		e.regionFor.keyword('{').append[newLine],
        	e.regionFor.keyword('}').prepend[newLine],
        	[indent]
    	)

		e.block.format

		for (c : e.getComment()) {
			c.format;
		}
		for (a : e.getAnnotation()) {
			a.format
		}
	}

	def dispatch void format(MultipleCombinedBehaviour e, extension IFormattableDocument document) {
	    interior(
       		e.regionFor.keyword('{').append[newLine],
        	e.regionFor.keyword('}').prepend[newLine],
        	[indent]
    	)

		for (b : e.block) {
			b.format
		}

		for (c : e.getComment()) {
			c.format;
		}
		for (a : e.getAnnotation()) {
			a.format
		}
	}

	def dispatch void format(ExceptionalBehaviour e, extension IFormattableDocument document) {
	    interior(
       		e.regionFor.keyword('{').append[newLine],
        	e.regionFor.keyword('}').prepend[newLine],
        	[indent]
    	)

		e.block.format

		for (c : e.getComment()) {
			c.format;
		}
		for (a : e.getAnnotation()) {
			a.format
		}
	}


	def dispatch void format(PeriodicBehaviour e, extension IFormattableDocument document) {
	    interior(
       		e.regionFor.keyword('{').append[newLine],
        	e.regionFor.keyword('}').prepend[newLine],
        	[indent]
    	)

		e.block.format

		for (c : e.getComment()) {
			c.format;
		}
		for (a : e.getAnnotation()) {
			a.format
		}
	}



	def dispatch void format(Block e, extension IFormattableDocument document) {
	    interior(
       		e.regionFor.keyword('{').append[newLine],
        	e.regionFor.keyword('}').prepend[newLine],
        	[indent]
    	)

		for (b : e.behaviour) {
			b.append[newLine]
			b.format	
		}
	}


	def dispatch void format(Element e, extension IFormattableDocument document) {
		e.prepend[newLine]
        e.allRegionsFor.keyword(',').prepend[noSpace]
        e.allRegionsFor.keyword(';').prepend[noSpace]
	    
	    interior(
	       	e.regionFor.keyword('{').append[newLine],
        	e.regionFor.keyword('}').prepend[newLine],
        	[indent]
    	)

		for (c : e.getComment()) {
		    c.prepend[newLine]
			c.format;
		}
		for (a : e.getAnnotation()) {
			a.prepend[newLine]
			a.format
		}

	}

	def dispatch void format(Annotation e, extension IFormattableDocument document) {
		if (e.value.isNullOrEmpty) {
			e.prepend[newLine]
		    e.regionFor.keyword(';').append[newLine]
		} else {
			e.prepend[newLine]
		    e.regionFor.keyword(';').append[newLine]
		}
	}

	def dispatch void format(Comment e, extension IFormattableDocument document) {
//		e.prepend[indent]
		e.prepend[newLine]
	}

	
	// TODO: implement for Action, AlternativeBehaviour, Annotation, AnnotationType, AnyValueOrOmit, AnyValue, ParameterBinding, Assertion, Assignment, BehaviourDescription, Block, BoundedLoopBehaviour, Break, Comment, ComponentInstance, ComponentInstanceBinding, ComponentType, CompoundBehaviour, ConditionalBehaviour, Connection, DataElementMapping, DataInstanceUse, DataResourceMapping, DefaultBehaviour, ElementImport, Function, FunctionCall, GateInstance, GateReference, GateType, InlineAction, Message, ProcedureCall, InterruptBehaviour, Member, MemberAssignment, ParameterMapping, OmitValue, ParallelBehaviour, FormalParameter, TimeLabelUse, FormalParameterUse, PeriodicBehaviour, Quiescence, SimpleDataInstance, SimpleDataType, Procedure, ProcedureParameter, Stop, StructuredDataInstance, CollectionDataInstance, StructuredDataType, Target, TestConfiguration, TestDescription, TestDescriptionReference, TestObjective, Time, TimeConstraint, TimeLabel, TimeOut, Timer, TimerStart, TimerStop, UnboundedLoopBehaviour, Variable, VariableUse, VerdictAssignment, Wait
}
