#include "character.hpp"

//#include "stageentity.hpp"
#include "character_modelview.hpp"
#include "character_controller.hpp"
//#include "aicontrollers/character_aicontroller.hpp"

/*
Character::Character(const KungFlowGame *game, const PlayState *playState, const HumanGamer *humanGamer, int teamID, const Vector2 &position) : StageEntity(e_StageEntityType_Character), teamID(teamID), controller(nullptr) {
  modelView = new CharacterModelView(game, playState, this, teamID, position);
  //controller = new CharacterHumanController(game, playState, this, humanGamer);
}
*/

Character::Character(const KungFlowGame *game, const PlayState *playState, int teamID, const Vector2 &position) : StageEntity(e_StageEntityType_Character), teamID(teamID), controller(nullptr) {
  modelView = new CharacterModelView(game, playState, this, teamID, position);
  //controller = new CharacterAIController(game, playState, this);
}

Character::~Character() {
  if (controller != nullptr) delete controller;
  delete modelView;
}

void Character::GetSpriteBounds(Vector2 &center, Vector2 &radius) const {
  modelView->GetSpriteBounds(center, radius);
}

void Character::OnCollide(const StageEntity* entity) {
  GetModelView()->OnCollide(entity);
}

void Character::OnStepPhysicsTime() {

  // control
  if (GetController() != nullptr) {
    GetController()->OnStepPhysicsTime(GetModelView());
  }

  // update players' physics, based on the current situation
  GetModelView()->OnStepPhysicsTime();

  // copy planned state into queue so we can still alter it later on, without losing info on initially planned state
  GetModelView()->InitPhysicsStateQueue();

}

void Character::PostStepPhysicsTime() {

  // positions, state, etc
  GetModelView()->ApplyPhysicsStateQueue();

  // update players' physics
  GetModelView()->PostStepPhysicsTime();

}

void Character::Draw(const Viewport &viewport, const Camera &camera) const {
  modelView->Draw(viewport, camera);
}

// NOTICE! this object TAKES OVER RESPONSIBILITY OF THE CONTROLLER!
void Character::SetControllerOwnership(CharacterController *controller) {
  this->controller = controller;
}

CharacterController *Character::GetController() {
  return controller;
}

CharacterModelView *Character::GetModelView() { return modelView; }

const CharacterModelView *Character::GetModelView_const() const {
  return modelView;
}

Vector2 Character::GetPosition() const {
  return modelView->GetPosition();
}

void Character::SetPosition(const Vector2 &newPosition) {
  modelView->SetPosition(newPosition);
}

void Character::SetQueuedPosition(const Vector2 &newPosition) {
  modelView->SetQueuedPosition(newPosition);
}

float Character::GetZPosition() const {
  return modelView->GetZPosition();
}

void Character::SetZPosition(float newZPosition) {
  modelView->SetZPosition(newZPosition);
}

void Character::SetQueuedZPosition(float newZPosition) {
  modelView->SetQueuedZPosition(newZPosition);
}

Vector2 Character::GetMovement() const {
  return modelView->GetMovement();
}

void Character::SetMovement(const Vector2 &newMovement) {
  modelView->SetMovement(newMovement);
}

void Character::SetQueuedMovement(const Vector2 &newMovement) {
  modelView->SetQueuedMovement(newMovement);
}

float Character::GetZMovement() const {
  return modelView->GetZMovement();
}

void Character::SetZMovement(float newZMovement) {
  modelView->SetZMovement(newZMovement);
}

void Character::SetQueuedZMovement(float newZMovement) {
  modelView->SetQueuedZMovement(newZMovement);
}

float Character::GetRadius() const {
  return modelView->GetRadius();
}

float Character::GetHeight() const {
  return modelView->GetHeight();
}
