#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <string>

// 2D vector structure
struct Vector2 {
    float x, y;
    
    Vector2(float x = 0.0f, float y = 0.0f) : x(x), y(y) {}
    
    // Vector subtraction
    Vector2 operator-(const Vector2& other) const {
        return Vector2(x - other.x, y - other.y);
    }
    
    // Vector addition
    Vector2 operator+(const Vector2& other) const {
        return Vector2(x + other.x, y + other.y);
    }
    
    // Vector scalar multiplication
    Vector2 operator*(float scalar) const {
        return Vector2(x * scalar, y * scalar);
    }
    
    // Calculate vector magnitude
    float Magnitude() const {
        return std::sqrt(x * x + y * y);
    }
    
    // Normalize vector
    Vector2 Normalized() const {
        float mag = Magnitude();
        if (mag > 0.0f) {
            return Vector2(x / mag, y / mag);
        }
        return Vector2(0.0f, 0.0f);
    }
    
    // Calculate distance between two points
    float Distance(const Vector2& other) const {
        return (*this - other).Magnitude();
    }
    
    // Dot product
    float Dot(const Vector2& other) const {
        return x * other.x + y * other.y;
    }
};

// Target body part enumeration
enum class BodyPart {
    HEAD,
    CHEST,
    LIMBS,
    COUNT
};

// Target body part structure
struct TargetPoint {
    Vector2 position;           // Part position
    BodyPart part;              // Part type
    float hitMultiplier;        // Damage multiplier
    std::string partName;       // Part name
    
    TargetPoint(const Vector2& pos, BodyPart p, float multiplier, const std::string& name)
        : position(pos), part(p), hitMultiplier(multiplier), partName(name) {}
};

// Target class
class Target {
private:
    Vector2 center_;                        // Target center position
    std::vector<TargetPoint> bodyParts_;    // Body parts
    
public:
    explicit Target(const Vector2& centerPos) : center_(centerPos) {
        // Initialize body parts (relative to center position)
        bodyParts_.emplace_back(center_ + Vector2(0.0f, 1.5f), BodyPart::HEAD, 2.0f, "Head");
        bodyParts_.emplace_back(center_ + Vector2(0.0f, 0.0f), BodyPart::CHEST, 1.0f, "Chest");
        bodyParts_.emplace_back(center_ + Vector2(-0.8f, 0.5f), BodyPart::LIMBS, 0.7f, "Left Arm");
        bodyParts_.emplace_back(center_ + Vector2(0.8f, 0.5f), BodyPart::LIMBS, 0.7f, "Right Arm");
        bodyParts_.emplace_back(center_ + Vector2(-0.4f, -1.0f), BodyPart::LIMBS, 0.5f, "Left Leg");
        bodyParts_.emplace_back(center_ + Vector2(0.4f, -1.0f), BodyPart::LIMBS, 0.5f, "Right Leg");
    }
    
    // Get all body parts within hit circle range
    std::vector<TargetPoint> GetBodyPartsInRange(const Vector2& hitCenter, float radius) const {
        std::vector<TargetPoint> inRangeParts;
        
        for (const auto& part : bodyParts_) {
            if (part.position.Distance(hitCenter) <= radius) {
                inRangeParts.push_back(part);
            }
        }
        
        return inRangeParts;
    }
    
    // Get target center position
    Vector2 GetCenter() const { return center_; }
    
    // Move target to new position
    void MoveTo(const Vector2& newCenter) {
        Vector2 offset = newCenter - center_;
        center_ = newCenter;
        
        // Update all body part positions
        for (auto& part : bodyParts_) {
            part.position = part.position + offset;
        }
    }
};

// Smart targeting system class
class SmartTargetingSystem {
private:
    // Targeting priority configuration
    struct TargetingPriority {
        BodyPart part;
        int priority;
        float weight;
    };
    
    std::vector<TargetingPriority> priorityConfig_;
    
public:
    SmartTargetingSystem() {
        // Configure targeting priorities (lower number = higher priority)
        priorityConfig_ = {
            {BodyPart::HEAD, 1, 2.0f},     // Head: highest priority
            {BodyPart::CHEST, 2, 1.0f},    // Chest: medium priority
            {BodyPart::LIMBS, 3, 0.5f}     // Limbs: lowest priority
        };
    }
    
    // Select best target part
    TargetPoint SelectBestTarget(const std::vector<TargetPoint>& availableParts, 
                                const Vector2& attackOrigin) const {
        if (availableParts.empty()) {
            throw std::runtime_error("No available target parts");
        }
        
        TargetPoint bestTarget = availableParts[0];
        float bestScore = -1.0f;
        
        for (const auto& part : availableParts) {
            float score = CalculateTargetScore(part, attackOrigin);
            
            if (score > bestScore) {
                bestScore = score;
                bestTarget = part;
            }
        }
        
        return bestTarget;
    }
    
private:
    // Calculate comprehensive score for target part
    float CalculateTargetScore(const TargetPoint& target, const Vector2& attackOrigin) const {
        float priorityScore = GetPriorityScore(target.part);
        float distanceScore = CalculateDistanceScore(target.position, attackOrigin);
        float damageScore = target.hitMultiplier;
        
        // Comprehensive score formula: priority weight * distance adaptability * damage multiplier
        return priorityScore * distanceScore * damageScore;
    }
    
    // Get priority score for body part
    float GetPriorityScore(BodyPart part) const {
        for (const auto& config : priorityConfig_) {
            if (config.part == part) {
                return config.weight;
            }
        }
        return 0.5f; // Default value
    }
    
    // Calculate distance adaptability score (closer distance = higher score)
    float CalculateDistanceScore(const Vector2& targetPos, const Vector2& attackOrigin) const {
        float distance = targetPos.Distance(attackOrigin);
        // Use inverse proportion function: closer distance = higher score
        return 1.0f / (1.0f + distance * 0.1f);
    }
};

// Hit circle class
class HitCircle {
private:
    Vector2 center_;
    float radius_;
    float baseDamage_;
    
public:
    HitCircle(const Vector2& center, float radius, float damage)
        : center_(center), radius_(radius), baseDamage_(damage) {}
    
    // Execute smart targeting attack
    void ExecuteSmartAttack(const Target& target, const Vector2& attackOrigin) const {
        SmartTargetingSystem targetingSystem;
        
        // Get all body parts within range
        auto partsInRange = target.GetBodyPartsInRange(center_, radius_);
        
        if (partsInRange.empty()) {
            std::cout << "Attack missed! No body parts hit." << std::endl;
            return;
        }
        
        try {
            // Select best target part
            TargetPoint bestTarget = targetingSystem.SelectBestTarget(partsInRange, attackOrigin);
            
            // Calculate final damage
            float finalDamage = baseDamage_ * bestTarget.hitMultiplier;
            
            // Output attack result
            std::cout << "Lock successful! Hit target " << bestTarget.partName 
                      << ", dealing " << finalDamage << " damage." << std::endl;
            std::cout << "Hit position: (" << bestTarget.position.x 
                      << ", " << bestTarget.position.y << ")" << std::endl;
                      
        } catch (const std::exception& e) {
            std::cout << "Lock failed: " << e.what() << std::endl;
        }
    }
    
    // Display all available target parts in hit circle (for debugging)
    void DisplayAvailableTargets(const Target& target) const {
        auto partsInRange = target.GetBodyPartsInRange(center_, radius_);
        
        std::cout << "Available target parts in hit circle (" << partsInRange.size() << "):" << std::endl;
        for (const auto& part : partsInRange) {
            std::cout << "  - " << part.partName << " (Damage multiplier: " << part.hitMultiplier 
                      << ", Position: " << part.position.x << ", " << part.position.y << ")" << std::endl;
        }
    }
    
    Vector2 GetCenter() const { return center_; }
    float GetRadius() const { return radius_; }
};

// Test example
int main() {
    std::cout << "=== Hit Circle Smart Targeting System Demo ===" << std::endl;
    
    // Create target
    Target target(Vector2(5.0f, 5.0f));
    std::cout << "Target created at position: (" << target.GetCenter().x 
              << ", " << target.GetCenter().y << ")" << std::endl;
    
    // Create hit circle (covering part of target's body)
    HitCircle hitCircle(Vector2(5.0f, 6.0f), 2.0f, 50.0f);
    std::cout << "Hit circle position: (" << hitCircle.GetCenter().x 
              << ", " << hitCircle.GetCenter().y << "), Radius: " 
              << hitCircle.GetRadius() << std::endl;
    
    // Display available target parts
    std::cout << "\n--- Available Target Parts Analysis ---" << std::endl;
    hitCircle.DisplayAvailableTargets(target);
    
    // Execute smart attack
    std::cout << "\n--- Executing Smart Attack ---" << std::endl;
    Vector2 attackOrigin(0.0f, 0.0f); // Attack origin position
    hitCircle.ExecuteSmartAttack(target, attackOrigin);
    
    // Test different positions
    std::cout << "\n--- Testing Different Hit Circle Positions ---" << std::endl;
    HitCircle hitCircle2(Vector2(4.5f, 5.5f), 1.5f, 50.0f);
    hitCircle2.DisplayAvailableTargets(target);
    hitCircle2.ExecuteSmartAttack(target, attackOrigin);
    
    // Test moving target
    std::cout << "\n--- Testing Moving Target ---" << std::endl;
    target.MoveTo(Vector2(8.0f, 8.0f));
    HitCircle hitCircle3(Vector2(8.0f, 9.0f), 2.0f, 50.0f);
    hitCircle3.DisplayAvailableTargets(target);
    hitCircle3.ExecuteSmartAttack(target, attackOrigin);
    
    return 0;
}