package legacypacket

import (
	"github.com/akmalfairuz/legacy-version/legacyver/proto"
	"github.com/go-gl/mathgl/mgl32"
	"github.com/sandertv/gophertunnel/minecraft/protocol"
	"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
)

// CorrectPlayerMovePrediction is sent by the server if and only if StartGame.ServerAuthoritativeMovementMode
// is set to AuthoritativeMovementModeServerWithRewind. The packet is used to correct movement at a specific
// point in time.
type CorrectPlayerMovePrediction struct {
	// PredictionType is the type of prediction that was corrected. It is one of the constants above.
	PredictionType byte
	// Position is the position that the player is supposed to be at the tick written in the field below.
	// The client will change its current position based on movement after that tick starting from the
	// Position.
	Position mgl32.Vec3
	// Delta is the change in position compared to what the client sent as its position at that specific tick.
	Delta mgl32.Vec3
	// Rotation is the rotation of the player at the tick written in the field below. It is only included if
	// PredictionType is PredictionTypeVehicle.
	// NOTE: As of 1.21.100, this field is also used for player rotations, and is not only set for vehicles.
	Rotation mgl32.Vec2
	// VehicleAngularVelocity is the angular velocity of the vehicle that the rider is riding.
	VehicleAngularVelocity protocol.Optional[float32]
	// OnGround specifies if the player was on the ground at the time of the tick below.
	OnGround bool
	// Tick is the tick of the movement which was corrected by this packet.
	Tick uint64
}

// ID ...
func (*CorrectPlayerMovePrediction) ID() uint32 {
	return packet.IDCorrectPlayerMovePrediction
}

func (pk *CorrectPlayerMovePrediction) Marshal(io protocol.IO) {
	if proto.IsProtoGTE(io, proto.ID671) {
		io.Uint8(&pk.PredictionType)
	}
	io.Vec3(&pk.Position)
	io.Vec3(&pk.Delta)
	if (proto.IsProtoGTE(io, proto.ID671) && proto.IsProtoLT(io, proto.ID827) && pk.PredictionType == packet.PredictionTypeVehicle) ||
		proto.IsProtoGTE(io, proto.ID827) {

		io.Vec2(&pk.Rotation)
		if proto.IsProtoGTE(io, proto.ID712) {
			protocol.OptionalFunc(io, &pk.VehicleAngularVelocity, io.Float32)
		}
	}
	io.Bool(&pk.OnGround)
	io.Varuint64(&pk.Tick)
}
