#include "Runtime/MP1/World/CEnergyBall.hpp"

#include "Runtime/CSimplePool.hpp"
#include "Runtime/CStateManager.hpp"
#include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/World/CPatternedInfo.hpp"
#include "Runtime/World/CPlayer.hpp"

namespace metaforce::MP1 {
CEnergyBall::CEnergyBall(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
                         CModelData&& mData, const CActorParameters& actParms, const CPatternedInfo& pInfo, s32 w1,
                         float f1, const CDamageInfo& dInfo1, float f2, const CAssetId& a1, s16 sfxId1,
                         const CAssetId& a2, const CAssetId& a3, s16 sfxId2, float f3, float f4, const CAssetId& a4,
                         const CDamageInfo& dInfo2, float f5)
: CPatterned(ECharacter::EnergyBall, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
             EMovementType::Flyer, EColliderType::One, EBodyType::NewFlyer, actParms, EKnockBackVariant::Medium)
, x570_(w1)
, x574_(f1)
, x578_(dInfo1)
, x594_initialTurnSpeed(pInfo.GetTurnSpeed())
, x598_(f2)
, x59c_(a1)
, x5a0_(sfxId1)
, x5a4_(a2)
, x5a8_(g_SimplePool->GetObj({FOURCC('ELSC'), a3}))
, x5b4_(sfxId2)
, x5b8_(f3)
, x5bc_(f4)
, x5c0_(g_SimplePool->GetObj({FOURCC('PART'), a4}))
, x5cc_(dInfo2)
, x5e8_(f5) {
  x460_knockBackController.SetEnableExplodeDeath(false);
  x460_knockBackController.SetAutoResetImpulse(false);
  x460_knockBackController.SetEnableBurnDeath(false);
  x460_knockBackController.SetX82_24(false);
  x460_knockBackController.SetEnableBurn(false);
  x460_knockBackController.SetEnableLaggedBurnDeath(false);
  x460_knockBackController.SetEnableShock(false);
  x460_knockBackController.SetEnableFreeze(false);
  x460_knockBackController.SetX81_31(false);
}

void CEnergyBall::Think(float dt, CStateManager& mgr) {
  float newTurnSpeed = x594_initialTurnSpeed * zeus::clamp(0.f, (x56c_ - 2.5f) * 0.125f, 1.f);
  x3b8_turnSpeed = newTurnSpeed;
  x450_bodyController->SetTurnSpeed(newTurnSpeed);
  CPatterned::Think(dt, mgr);
  GetModelData()->GetAnimationData()->GetParticleDB().SetModulationColorAllActiveEffects(
      zeus::CColor::lerp(zeus::skWhite, zeus::skRed, zeus::clamp(0.f, x428_damageCooldownTimer / 0.33f, 1.f)));

  bool r27 = false;
  if (GetActive() && IsAlive()) {
    x56c_ -= dt;
    if (x56c_ > x574_)
      r27 = true;
    if (!InMaxRange(mgr, dt))
      r27 = true;
  }

  if (!r27)
    sub8029f4a8(mgr);
}

void CEnergyBall::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
  if (msg == EScriptObjectMessage::Registered) {
    SetMaterialFilter(CMaterialFilter::MakeInclude({EMaterialTypes::Player}));
    RemoveMaterial(EMaterialTypes::Solid, mgr);
  }
  CPatterned::AcceptScriptMsg(msg, uid, mgr);
}

void CEnergyBall::Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState /* state */) {
  CHealthInfo* hInfo = HealthInfo(mgr);
  if (hInfo && hInfo->GetHP() > 0.f) {
    CPatterned::Death(mgr, direction, EScriptObjectState::Any);
  } else {
    CPatterned::Death(mgr, direction, EScriptObjectState::DeathRattle);
  }
}

void CEnergyBall::Generate(CStateManager& mgr, EStateMsg msg, float /*arg*/) {
  if (msg == EStateMsg::Activate || msg == EStateMsg::Update) {
    if (msg == EStateMsg::Activate)
      x32c_animState = EAnimState::Ready;

    TryGenerateDeactivate(mgr, 0);

    if (!x450_bodyController->GetActive())
      x450_bodyController->Activate(mgr);
  } else if (msg == EStateMsg::Deactivate) {
    x32c_animState = EAnimState::NotReady;
  }
}

void CEnergyBall::Attack(CStateManager& mgr, EStateMsg msg, float arg) {
  if (msg == EStateMsg::Update) {
    zeus::CVector3f seekPos = x568_steeringBehaviors.Seek(*this, mgr.GetPlayer().GetEyePosition());
    x450_bodyController->FaceDirection3D(seekPos, GetTransform().basis[1], arg);
  }
}
void CEnergyBall::sub8029f4a8(CStateManager& mgr) {}
}