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

namespace frostbite2D {
namespace {

CharacterStateId ResolveInterruptedState(const CharacterStateContext& context) {
  auto& motor = context.owner.GetMotorMutable();
  if (!motor.grounded) {
    return CharacterStateId::Fall;
  }
  return (std::abs(context.intent.moveX) > 0.01f || std::abs(context.intent.moveY) > 0.01f)
      ? CharacterStateId::Move
      : CharacterStateId::Idle;
}

} // namespace

HurtState::HurtState()
    : CharacterStateBase(CharacterStateId::Hurt) {
}

void HurtState::OnEnter(CharacterStateMachine& machine,
                        CharacterStateContext& context,
                        CharacterStateId previousState) {
  (void)previousState;
  const CharacterActionDefinition* action = GetCurrentAction(machine);
  if (!action) {
    context.owner.ReportFatalCharacterError("HurtState::OnEnter",
                                            "hurt state entered without current action");
    return;
  }

  context.owner.PlayAnimationTag(action->actionId);
  InvokeHook(machine, context.owner, action, "on_enter");
}

void HurtState::OnUpdate(CharacterStateMachine& machine,
                         CharacterStateContext& context) {
  auto& owner = context.owner;
  auto& motor = owner.GetMotorMutable();
  motor.StopGroundMovement();

  const CharacterActionDefinition* action = GetCurrentAction(machine);
  if (!action) {
    owner.ReportFatalCharacterError("HurtState::OnUpdate",
                                    "hurt state updated without current action");
    return;
  }

  InvokeHook(machine, owner, action, "on_update");

  if (owner.IsCurrentAnimationFinished()) {
    ClearCurrentAction(machine);
    context.owner.SetFacing(motor.facing);
    ChangeState(machine, context, ResolveInterruptedState(context));
  }
}

void HurtState::OnExit(CharacterStateMachine& machine,
                       CharacterStateContext& context,
                       CharacterStateId nextState) {
  (void)nextState;
  InvokeHook(machine, context.owner, GetCurrentAction(machine), "on_exit");
}

} // namespace frostbite2D
