﻿#include <algorithm>
#include <cmath>

#include "Shooting/ImageManager.h"
#include "Shooting/Input.h"
#include "Shooting/PlayerShotManager.h"
#include "Shooting/Tuning/GameTuning.h"

#include "Shooting/Player.h"

namespace dxgame::shooting
{
    using Action = Input::Action;

    void Player::Reset()
    {
        position = tuning::player::StartPosition;
        shotTimer = 0.0f;
    }

    void Player::Update(const Input& input, float deltaTime)
    {
        Vector2 direction;

        if (input.IsDown(Action::MoveLeft))
            direction.x -= 1.0f;
        if (input.IsDown(Action::MoveRight))
            direction.x += 1.0f;
        if (input.IsDown(Action::MoveUp))
            direction.y -= 1.0f;
        if (input.IsDown(Action::MoveDown))
            direction.y += 1.0f;

        // 斜め入力を長さ1に収める
        // 方向と長さの計算は第05回で詳しく扱う
        float length = std::sqrt(direction.x * direction.x + direction.y * direction.y);

        if (length > 1.0f)
        {
            direction.x /= length;
            direction.y /= length;
        }

        position.x += direction.x * tuning::player::MoveSpeed * deltaTime;
        position.y += direction.y * tuning::player::MoveSpeed * deltaTime;

        // 指定の範囲全体が画面内に残るよう位置を制限する
        const Rect& bounds = tuning::player::Bounds;

        float minX = -bounds.x;
        float minY = -bounds.y;
        float maxX = tuning::ScreenWidth - bounds.x - bounds.width;
        float maxY = tuning::ScreenHeight - bounds.y - bounds.height;
        position.x = std::clamp(position.x, minX, maxX);
        position.y = std::clamp(position.y, minY, maxY);

        shotTimer = std::max(0.0f, shotTimer - deltaTime);
    }

    void Player::Draw(const ImageManager& images) const
    {
        images.Draw(ImageManager::Id::Player, GetDrawRect());
    }

    bool Player::TryShoot(const Input& input, PlayerShotManager& shots)
    {
        if (!input.IsDown(Action::Shoot) || shotTimer > 0.0f)
            return false;

        if (!shots.Spawn(GetMuzzlePosition()))
            return false;

        shotTimer = tuning::player::ShotInterval;
        return true;
    }

Vector2 Player::GetMuzzlePosition() const
{
    return
    {
        position.x,
        position.y - 32.0f
    };
}

    Rect Player::GetDrawRect() const
    {
        return tuning::player::DrawRect.MovedBy(position);
    }

    Rect Player::GetHitbox() const
    {
        return tuning::player::Hitbox.MovedBy(position);
    }
}
