package org.openstreetmap.josm.io;

import org.junit.Test 
import org.openstreetmap.josm.data.coor.LatLon 
import org.openstreetmap.josm.data.osm.Changeset 

import static org.junit.Assert.*;
 
class OsmChangeBuilderTest {
	
	/**
	 * Test various constructor invocations 
	 */
	@Test
	public void testConstructor() {
		def Changeset cs = new Changeset(1)
		// should not fail 
		OsmChangeBuilder builder = new OsmChangeBuilder(cs)
		
		// should not fail either - null allowed
		builder = new OsmChangeBuilder(null)
		
		// should not fail 
		builder = new OsmChangeBuilder(cs, "0.5")
		
		builder = new OsmChangeBuilder(cs, null)
		
		builder = new OsmChangeBuilder(null, null)      
	}
	
	/**
	 * Test the sequence of method calls. Should throw IllegalStateException if
	 * the protocol start(),append()*, finish() is violated.
	 */
	@Test
	public void testSequenceOfMethodCalls() {
		def Changeset cs = new Changeset(1) 
		OsmChangeBuilder builder = new OsmChangeBuilder(cs)
		
		final shouldFail = new GroovyTestCase().&shouldFail
		
		// should be OK 
		builder.start()
		Node n = new Node(new LatLon(0,0))
		builder.append n
		builder.finish()
		
		shouldFail(IllegalStateException) {
			builder = new OsmChangeBuilder(cs)
			builder.append n
		}
		
		shouldFail(IllegalStateException) {
			builder = new OsmChangeBuilder(cs)
			builder.append([n])
		}
		
		shouldFail(IllegalStateException) {
			builder = new OsmChangeBuilder(cs)
			builder.finish()
		}
		
		shouldFail(IllegalStateException) {
			builder = new OsmChangeBuilder(cs)
			builder.start()
			builder.start()
		}       
	}
	
	@Test
	public void testDocumentWithNewNode() {
		def Changeset cs = new Changeset(1) 
		OsmChangeBuilder builder = new OsmChangeBuilder(cs)
		Node n = new Node(new LatLon(0,0))
		
		builder.start()
		builder.append n
		builder.finish()
		
		def doc = new XmlParser().parseText(builder.document)
		assert doc.@version == "0.6"
		assert doc.@generator == "JOSM"
		assert doc.name() == "osmChange"
		assert doc.children().size() == 1
		def create = doc.create
		assert create != null
		
		assert create.size() == 1
		def nodes = create[0].node
		assert nodes.size() == 1
		def node = nodes[0]
		assert node.@id == n.uniqueId.toString()
		assert node.@lat != null
		assert node.@lon != null
		assert node.@changeset == cs.id.toString()      
	}   
	
	/**
	 * Test building a document with a modified node 
	 */
	@Test
	public void testDocumentWithModifiedNode() {
		def Changeset cs = new Changeset(1) 
		OsmChangeBuilder builder = new OsmChangeBuilder(cs)
		Node n = new Node(1)
		n.coor = new LatLon(0,0)
		n.incomplete = false
		n.modified = true
		
		builder.start()
		builder.append n
		builder.finish()
		
		def doc = new XmlParser().parseText(builder.document)
		assert doc.@version == "0.6"
		assert doc.@generator == "JOSM"
		assert doc.name() == "osmChange"
		assert doc.children().size() == 1
		def modify = doc.modify
		assert modify != null
		
		assert modify.size() == 1
		def nodes = modify[0].node
		assert nodes.size() == 1
		def node = nodes[0]
		assert node.@id == n.uniqueId.toString()
		assert node.@lat != null
		assert node.@lon != null
		assert node.@changeset == cs.id.toString()      
	}   
	
	/**
	 * Test building a document with a deleted node 
	 */
	@Test
	public void testDocumentWithDeletedNode() {
		def Changeset cs = new Changeset(1) 
		OsmChangeBuilder builder = new OsmChangeBuilder(cs)
		Node n = new Node(1)
		n.coor = new LatLon(0,0)
		n.incomplete = false
		n.deleted = true
		
		builder.start()
		builder.append n
		builder.finish()
		
		def doc = new XmlParser().parseText(builder.document)
		assert doc.@version == "0.6"
		assert doc.@generator == "JOSM"
		assert doc.name() == "osmChange"
		assert doc.children().size() == 1
		def delete = doc.delete
		assert delete != null
		
		assert delete.size() == 1
		def nodes = delete[0].node
		assert nodes.size() == 1
		def node = nodes[0]
		assert node.@id == n.uniqueId.toString()
		assert node.@lat != null
		assert node.@lon != null
		assert node.@changeset == cs.id.toString()      
	}
	
	/**
	 * Test building a mixed document. 
	 *  
	 */
	@Test
	public void testMixed() {
		def Changeset cs = new Changeset(1) 
		OsmChangeBuilder builder = new OsmChangeBuilder(cs)
		Node n1 = new Node(1)
		n1.coor = new LatLon(0,0)
		n1.incomplete = false
		n1.deleted = true
		
		Node n2 = new Node(new LatLon(0,0))
		
		Node n3 = new Node(2)
		n3.coor = new LatLon(0,0)
		n3.incomplete = false
		n3.modified = true
		
		builder.start()
		builder.append([n1,n2,n3])
		builder.finish()
		
		def doc = new XmlParser().parseText(builder.document)
		
		assert doc.children().size() == 3
		assert doc.children()[0].name() == "delete"
		assert doc.children()[1].name() == "create"
		assert doc.children()[2].name() == "modify"
		
		def node = doc.children()[0].node[0]
		assert node.@id == n1.uniqueId.toString()
		
		node = doc.children()[1].node[0]
		assert node.@id == n2.uniqueId.toString()
		
		node = doc.children()[2].node[0]
		assert node.@id == n3.uniqueId.toString()       
	}
}
