#include "server/entities/ServerPlayer.h"
#include "common/network/toclient/EntityUpdatePacket.h"
#include "server/Game.h"
#include "server/GameServer.h"
#include "utils/Logger.h"

ServerPlayer::ServerPlayer(Server::Client& client) : client(client) {
    skip = true;
}

void ServerPlayer::tick() {
    if(!history.canRead()) {
        LOG_DEBUG("No data");
        return;
    }
    PlayerUpdatePacket p = history.read();

    Vector3 move = p.position - position;
    float xzDistance = Vector2(move[0], move[2]).squareLength();
    float maxXZDistance = getMaxXZVelocity();
    maxXZDistance *= maxXZDistance;
    maxXZDistance *= 1.01f;
    if(xzDistance > maxXZDistance) {
        setClientPosition();
        return;
    }
    if(move[1] > 0.4f) {
        jump();
    }
    Entity::tick();

    Vector3 actualClientMove = Game::world.limitMove(*this, move);
    Vector3 actualServerMove =
        Game::world.limitMove(*this, Vector3(move[0], velocity[1], move[2]));

    float distance = (actualClientMove - actualServerMove).squareLength();
    if(distance > 0.001f) {
        actualClientMove = actualServerMove;
    }
    this->move(actualClientMove);
    if((move - actualClientMove).squareLength() > 0.05f) {
        setClientPosition();
    }
    velocity[0] = 0.0f;
    velocity[2] = 0.0f;
}

void ServerPlayer::onChat(InPacket& in) {
    (void)in;
}

void ServerPlayer::send(OutPacket& out) {
    client.send(out);
}

void ServerPlayer::onUpdatePacket(const PlayerUpdatePacket& p) {
    if(history.write(p)) {
        LOG_WARNING("FULL QUEUE");
    }
}

void ServerPlayer::setClientPosition() {
    history.clear();
    EntityUpdatePacket e(*this);
    OutPacket out = OutPacket::sequenced(EntityUpdatePacket::getSize());
    e.write(out);
    GameServer::sendToAll(out);
}