#include "pingpong_ball.h"

#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/variant/utility_functions.hpp>
#include <godot_cpp/classes/engine.hpp>
#include <godot_cpp/classes/kinematic_collision2d.hpp>
#include <godot_cpp/classes/node2d.hpp>
#include <godot_cpp/classes/viewport.hpp>
#include <godot_cpp/classes/window.hpp>
#include <godot_cpp/classes/scene_tree.hpp>

using namespace godot;

// ═══════════════════════════════════════════════════════
// 视觉颜色常量 — 以后替换素材时删除本段
// ═══════════════════════════════════════════════════════
static const Color BALL_COLOR = Color(1.0f, 1.0f, 1.0f);

void PingPongBall::_bind_methods() {
    // 属性
    ClassDB::bind_method(D_METHOD("get_speed"), &PingPongBall::get_speed);
    ClassDB::bind_method(D_METHOD("set_speed", "value"), &PingPongBall::set_speed);
    ClassDB::add_property("PingPongBall", PropertyInfo(Variant::FLOAT, "speed"), "set_speed", "get_speed");

    ClassDB::bind_method(D_METHOD("get_initial_speed"), &PingPongBall::get_initial_speed);
    ClassDB::bind_method(D_METHOD("set_initial_speed", "value"), &PingPongBall::set_initial_speed);
    ClassDB::add_property("PingPongBall", PropertyInfo(Variant::FLOAT, "initial_speed"), "set_initial_speed", "get_initial_speed");

    ClassDB::bind_method(D_METHOD("get_active"), &PingPongBall::get_active);
    ClassDB::bind_method(D_METHOD("set_active", "value"), &PingPongBall::set_active);

    // 方法
    ClassDB::bind_method(D_METHOD("reset"), &PingPongBall::reset);

    // 信号
    ADD_SIGNAL(MethodInfo("scored", PropertyInfo(Variant::INT, "which")));
}

PingPongBall::PingPongBall() {
    speed = 350.0f;
    initial_speed = 350.0f;
    is_active = false;
}

PingPongBall::~PingPongBall() {
}

void PingPongBall::_ready() {
    reset();
}

// ═══════════════════════════════════════════════════════
// 视觉层 — 球体 + 拖尾（几何体占位）
// 替换方法：删除本方法 → 添加 Sprite2D 子节点
// ═══════════════════════════════════════════════════════
void PingPongBall::_draw() {
    // 拖尾：从旧到新画渐隐圆
    int trail_count = (int)trail_positions.size();
    for (int i = 0; i < trail_count; i++) {
        float alpha = (float)(i + 1) / (float)BALL_TRAIL_LENGTH * 0.3f;
        float radius = BALL_RADIUS * (0.5f + 0.5f * (float)(i + 1) / (float)BALL_TRAIL_LENGTH);
        draw_circle(trail_positions[i], radius, Color(1.0f, 1.0f, 1.0f, alpha));
    }

    // 球本体
    draw_circle(Vector2(0.0f, 0.0f), BALL_RADIUS, BALL_COLOR);
}

void PingPongBall::_physics_process(double delta) {
    queue_redraw();

    if (!is_active) {
        return;
    }

    // 更新拖尾
    trail_positions.push_back(get_position());
    if ((int)trail_positions.size() > BALL_TRAIL_LENGTH) {
        trail_positions.erase(trail_positions.begin());
    }

    Vector2 velocity = direction * speed * (float)delta;

    Ref<KinematicCollision2D> collision = move_and_collide(velocity);

    if (collision.is_valid()) {
        Vector2 normal = collision->get_normal();
        direction = direction.bounce(normal);

        Object *collider = collision->get_collider();
        if (collider) {
            Node *collider_node = Object::cast_to<Node>(collider);
            if (collider_node) {
                StringName node_name = collider_node->get_name();
                // 碰到球拍
                if (node_name.find("Paddle") != -1) {
                    Node2D *collider_2d = Object::cast_to<Node2D>(collider_node);
                    if (collider_2d) {
                        // 根据击中位置微调角度
                        float hit_offset = (get_global_position().y - collider_2d->get_global_position().y) / 60.0f;
                        hit_offset = CLAMP(hit_offset, -1.0f, 1.0f);
                        direction.y += hit_offset * 0.5f;
                        direction = direction.normalized();

                        // 速度递增
                        speed *= BALL_SPEED_INCREMENT;
                        if (speed > BALL_MAX_SPEED) {
                            speed = BALL_MAX_SPEED;
                        }
                    }
                }
            }
        }

        direction = direction.normalized();
    }

    // 得分判定
    Viewport *viewport = get_viewport();
    if (viewport) {
        Vector2 screen_size = viewport->get_visible_rect().size;
        Vector2 pos = get_global_position();

        if (pos.x < -50.0f) {
            emit_signal("scored", 1);
            reset();
        } else if (pos.x > screen_size.x + 50.0f) {
            emit_signal("scored", 0);
            reset();
        }

        // Y 边界限制
        if (pos.y < BALL_RADIUS) {
            set_global_position(Vector2(pos.x, BALL_RADIUS));
            direction.y = std::abs(direction.y);
        } else if (pos.y > screen_size.y - BALL_RADIUS) {
            set_global_position(Vector2(pos.x, screen_size.y - BALL_RADIUS));
            direction.y = -std::abs(direction.y);
        }
    }
}

void PingPongBall::reset() {
    Viewport *viewport = get_viewport();
    if (viewport) {
        Vector2 screen_size = viewport->get_visible_rect().size;
        set_global_position(screen_size / 2.0f);
    } else {
        set_global_position(Vector2(640.0f, 360.0f));
    }

    // 重置速度
    speed = initial_speed;

    // 清空拖尾
    trail_positions.clear();

    // 随机方向
    float angle = (UtilityFunctions::randf() - 0.5f) * Math_PI / 2.0f;
    int side = (UtilityFunctions::randf() > 0.5f) ? 1 : -1;
    direction = Vector2((float)side * std::cos(angle), std::sin(angle)).normalized();

    // 确保水平分量足够
    if (std::abs(direction.x) < 0.3f) {
        direction.x = (direction.x > 0 ? 1.0f : -1.0f) * 0.3f;
        direction = direction.normalized();
    }
}

void PingPongBall::set_active(bool p_active) {
    is_active = p_active;
}

bool PingPongBall::get_active() const {
    return is_active;
}

void PingPongBall::set_speed(float p_speed) {
    speed = p_speed;
}

float PingPongBall::get_speed() const {
    return speed;
}

void PingPongBall::set_initial_speed(float p_speed) {
    initial_speed = p_speed;
}

float PingPongBall::get_initial_speed() const {
    return initial_speed;
}
