func TestProcessorFactory(t *testing.T) {
	Convey("ProcessorFactory", t, func() {
		physics := processor.DefaultPhysics()
		physics.TurnCommandModifier = 1.0
		physics.AccelerationCommandModifier = 1.0
		factory := processor.NewFactory(&physics)

		t := cmd.NewTurn(1)
		t_comm := cmd.GameCommand(&t)
		turn_cp := factory.GetCommandProcessor(&t_comm)
		So(turn_cp, ShouldHaveSameTypeAs, &processor.TurnCommandProcessor{Physics: &physics})

		a := cmd.NewAcceleration(1)
		a_comm := cmd.GameCommand(&a)
		acceleration_cp := factory.GetCommandProcessor(&a_comm)
		So(acceleration_cp, ShouldHaveSameTypeAs, &processor.AccelerationCommandProcessor{Physics: &physics})

		c := cmd.NewConnect("test")
		c_comm := cmd.GameCommand(&c)
		connect_cp := factory.GetCommandProcessor(&c_comm)
		So(connect_cp, ShouldHaveSameTypeAs, &processor.ConnectCommandProcessor{Physics: &physics})

		f := cmd.NewFire()
		f_comm := cmd.GameCommand(&f)
		fire_cp := factory.GetCommandProcessor(&f_comm)
		So(fire_cp, ShouldHaveSameTypeAs, &processor.FireCommandProcessor{Physics: &physics})

		b := cmd.BaseCommand{}
		b_comm := cmd.GameCommand(&b)
		base_cp := factory.GetCommandProcessor(&b_comm)
		So(base_cp, ShouldEqual, nil)
	})
}
func TestRoutePost(t *testing.T) {
	ack_channel := make(chan state.Ack, 100)
	state_channel := make(chan state.StateResponse, 100)

	physics := processor.DefaultPhysics()
	factory := processor.CommandProcessorFactory{Physics: &physics}

	gameState := physics.NewGameState()

	gameManager := NewManager(gameState, state_channel, &factory)

	router := CommandRouter{Acks: ack_channel, GameManager: &gameManager}
	address, err := net.ResolveUDPAddr("udp", "127.0.0.1:8080")

	Convey("Route Post", t, func() {
		So(err, ShouldEqual, nil)
		turn := cmd.NewTurn(.4)
		cmd := cmd.GameCommand(&turn)

		So(len(gameManager.commandsToProcess), ShouldEqual, 0)

		router.routePost(&cmd, address)
		resp := <-ack_channel

		So(resp.Address, ShouldEqual, address)
		So(len(gameManager.commandsToProcess), ShouldEqual, 1)
	})
}
func TestTurnProcessor(t *testing.T) {
	Convey("Turn Processor", t, func() {
		physics := processor.DefaultPhysics()
		physics.TurnCommandModifier = 1.0
		physics.AccelerationCommandModifier = 1.0
		conn_processor := processor.TurnCommandProcessor{Physics: &physics}

		c := cmd.NewTurn(.5)
		c2 := cmd.NewTurn(.2)
		c.UserId = "abc123"
		c2.UserId = "abc123"

		turn := cmd.GameCommand(&c)
		turn2 := cmd.GameCommand(&c2)

		game_state := physics.NewGameState()

		game_state.Vehicles = append(game_state.Vehicles, &(state.Vehicle{Owner: "abc123", Velocity: 0, IsAlive: true}))

		So(len(game_state.Vehicles), ShouldEqual, 1)
		So(game_state.Vehicles[0].Angle, ShouldAlmostEqual, 0, .0001)

		conn_processor.Run(&game_state, turn)
		So(game_state.Vehicles[0].Angle, ShouldAlmostEqual, 359.5, .0001)

		conn_processor.Run(&game_state, turn2)
		So(game_state.Vehicles[0].Angle, ShouldAlmostEqual, 359.3, .0001)

		turn2.Command().UserId = "blach"
		conn_processor.Run(&game_state, turn2)
		So(game_state.Vehicles[0].Angle, ShouldAlmostEqual, 359.3, .0001)

		//check rollover
		conn_processor.Run(&game_state, turn)
		So(game_state.Vehicles[0].Angle, ShouldAlmostEqual, 358.8, .0001)

		// check rollover
		c.Value = -1.4
		conn_processor.Run(&game_state, turn)
		So(game_state.Vehicles[0].Angle, ShouldAlmostEqual, .2, .0001)

	})
}
func TestTurn(t *testing.T) {
	Convey("Turn Command", t, func() {
		turn := cmd.NewTurn(.3)
		So(turn.UniqueId, ShouldEqual, "")
		So(turn.Subtype, ShouldEqual, cmd.Turn)
		So(turn.Type, ShouldEqual, cmd.Post)
		So(turn.Value, ShouldAlmostEqual, .3, .00001)
		So(turn.Type, ShouldEqual, turn.Command().Type)
		So(turn.Subtype, ShouldEqual, turn.Command().Subtype)
		So(turn.UniqueId, ShouldEqual, turn.Command().UniqueId)
	})
}
func main() {
	var waiter sync.WaitGroup
	waiter.Add(1)
	//get connection to host and sets a timeout for connection when completed
	conn, err := net.DialTimeout("udp", host, 1*time.Second)

	// start goroutine  to listen for messages
	go responsePrinter(conn)

	for i := 0; i < 12; i++ {

		if err != nil {
			log.Print(err)
		} else {
			var message []byte

			// creates unique identifier to be returned for the packet ack
			uuid := uuid.NewUUID().String()
			if i == 0 {
				a := cmd.NewConnect("Dan")
				a.UniqueId = uuid
				message, err = json.Marshal(a)
			} else {
				// randomly select between commands
				randType := rand.Intn(2)
				if randType == 0 {
					a := cmd.NewTurn(.5)
					a.UniqueId = uuid
					message, err = json.Marshal(a)
				}
				if randType == 1 {
					a := cmd.NewAcceleration(.5)
					a.UniqueId = uuid
					message, err = json.Marshal(a)
				}
			}

			//send the message
			conn.Write(message)

			time.Sleep(1 * time.Millisecond)
		}
	}
	waiter.Wait()

	//clean up connection
	conn.Close()

}
func TestDecodeTurn(t *testing.T) {
	Convey("Turn Decode", t, func() {
		formatter := encoder.JsonEncoderDecoder{Tag: "DecodeTest"}

		data := cmd.NewTurn(.2)
		data.UniqueId = "ABC123"
		buffer, error := json.Marshal(data)

		command, err := formatter.Decode(buffer)

		turn := command.(*cmd.TurnCommand)

		So(error, ShouldEqual, nil)
		So(turn.Command().Type, ShouldEqual, cmd.Post)
		So(turn.Command().Subtype, ShouldEqual, cmd.Turn)
		So(err, ShouldEqual, nil)
		So(turn.Value, ShouldAlmostEqual, .2, .000001)
		So(turn.Command().UniqueId, ShouldEqual, "ABC123")
	})
}