#include "character/states/common/LandingState.h"
#include "character/CharacterObject.h"
#include <cmath>

namespace frostbite2D {
namespace {

bool HasMoveIntent(const CharacterIntent& intent) {
  return intent.moveMode != CharacterMoveMode::None
      && (std::abs(intent.moveX) > 0.01f || std::abs(intent.moveY) > 0.01f);
}

} // namespace

LandingState::LandingState()
    : CharacterStateBase(CharacterStateId::Landing) {
}

void LandingState::OnEnter(CharacterStateMachine& machine,
                           CharacterStateContext& context,
                           CharacterStateId previousState) {
  (void)previousState;
  context.owner.PlayAnimationTag("landing");
  InvokeHook(machine, context.owner, context.owner.FindAction("landing"), "on_enter");
}

void LandingState::OnUpdate(CharacterStateMachine& machine,
                            CharacterStateContext& context) {
  auto& owner = context.owner;
  auto& motor = owner.GetMotorMutable();
  if (!motor.grounded) {
    ChangeState(machine, context, CharacterStateId::Fall);
    return;
  }

  motor.StopGroundMovement();
  if (!owner.IsCurrentAnimationFinished()) {
    return;
  }

  if (TryStartRegisteredAction(machine, context)) {
    return;
  }
  if (context.commandBuffer.HasBuffered(CharacterCommandType::JumpPressed)) {
    context.commandBuffer.Consume(CharacterCommandType::JumpPressed);
    motor.Jump();
    ChangeState(machine, context, CharacterStateId::Jump);
    return;
  }

  if (HasMoveIntent(context.intent)) {
    ChangeState(machine, context, CharacterStateId::Move);
    return;
  }

  ChangeState(machine, context, CharacterStateId::Idle);
}

} // namespace frostbite2D
