﻿#include <DxLib.h>

#include <string>

#include <Windows.h>

#include "Config/ApplicationConfig.h"
#include "Shooting/Tuning/GameTuning.h"

#include "Shooting/Game.h"

namespace
{
    void ShowResourceLoadError(
        const wchar_t* resourceType,
        const std::wstring& failedPath)
    {
        std::wstring message = resourceType;
        message += L"の読み込みに失敗しました。\n\n対象: ";
        message += failedPath;
        message += L"\n\nAssetsフォルダーとファイル名を確認してください。";

        MessageBoxW(
            nullptr,
            message.c_str(),
            L"リソース読み込みエラー",
            MB_OK | MB_ICONERROR);
    }
}

namespace dxgame::shooting
{
    namespace config = dxgame::config;

    bool Game::Run()
    {
        const ImageManager::LoadResult imageResult = images.LoadAll();
        if (!imageResult.succeeded)
        {
            ShowResourceLoadError(L"画像", imageResult.failedPath);
            return false;
        }

        player.Reset();
        playerShots.Reset();
        enemies.Reset();
        score = 0;

        // 小数分の待ち時間を次フレームへ持ち越す
        double nextFrame = GetNowCount();

        while (ProcessMessage() == 0)
        {
            input.Update();
            if (input.IsDown(Input::Action::Exit))
                break;

            Update(config::DeltaTime);
            ClearDrawScreen();
            Draw();
            ScreenFlip();

            nextFrame += config::FrameMilliseconds;
            int waitMilliseconds = static_cast<int>(nextFrame - GetNowCount());

            if (waitMilliseconds > 0)
                WaitTimer(waitMilliseconds);
            else
                nextFrame = GetNowCount();
        }

        return true;
    }

    void Game::Update(float deltaTime)
    {
        player.Update(input, deltaTime);
        playerShots.Update(deltaTime);
        enemies.Update(deltaTime);

        ResolveCollisions();

        player.TryShoot(input, playerShots);
    }

    void Game::Draw() const
    {
        // 描画順はプレイヤー、プレイヤーの弾、敵、敵の弾の順（存在するものだけ描画）
        player.Draw(images);
        playerShots.Draw(images);
        enemies.Draw(images);
        DrawFormatString(16, 16, GetColor(255, 255, 255), L"SCORE %02d", score);
    }

    void Game::ResolveCollisions()
    {
        for (PlayerShot& playerShot : playerShots.GetAll())
        {
            if (!playerShot.IsActive())
                continue;

            for (Enemy& enemy : enemies.GetAll())
            {
                if (!enemy.IsActive())
                    continue;

                if (!playerShot.GetHitbox().Overlaps(enemy.GetHitbox()))
                    continue;

                enemy.TakeDamage(tuning::playerShot::Damage);
                playerShot.Deactivate();

                if (!enemy.IsActive())
                    ++score;

                break;
            }
        }
    }
}
