mod config;
mod player;
mod enemy;
mod aimbot;

use std::time::{Instant, Duration};
use std::sync::atomic::{AtomicBool, Ordering};
use enemy::Enemy;
use player::{Player, Camera};
use aimbot::{LockingResult, Aimbot, TargetPriority};
use config::Config;

static RUNNING: AtomicBool = AtomicBool::new(true);

fn main() {
    let cfg = match config::load("config.toml") {
        Ok(cfg) => cfg,
        Err(_) => Config::default(),
    };

    let mut player = Player::spawn();
    let mut enemies = Enemy::demo_vec();
    let camera = Camera::new(cfg.core.fov);
    let mut bot = Aimbot::new(cfg.clone());

    let target_frame_time = Duration::from_millis(16);
    let mut last_frame_time = Instant::now();

    ctrlc::set_handler(|| {
        RUNNING.store(false, Ordering::SeqCst);
    }).expect("Failed to set signal handler");

    while RUNNING.load(Ordering::SeqCst) {
        let current_time = Instant::now();
        let _delta_time = current_time.duration_since(last_frame_time);

        for e in &mut enemies {
            e.tick(_delta_time);
        }

        static mut LAST_ADS_TOGGLE: Instant = Instant::now();
        unsafe {
            if try_toggle_ads(&player) && current_time.duration_since(LAST_ADS_TOGGLE) > Duration::from_millis(200) {
                player.ads = !player.ads;
                LAST_ADS_TOGGLE = current_time;
            }
        }

        static mut LAST_SHOOT_TIME: Instant = Instant::now();
        unsafe {
            let can_shoot = current_time.duration_since(LAST_SHOOT_TIME) > Duration::from_millis(bot.cfg.core.shoot_cooldown);
            
            if can_shoot {
                if is_fire_pressed() {
                    if let Some(LockingResult { shoot_pos, target }) = bot.fire_mode(&player, &camera, &enemies, TargetPriority::LowHealth) {
                        println!("FIRE {:?} {:?} {}", target.name, shoot_pos, target.health);
                        LAST_SHOOT_TIME = current_time;
                    }
                }

                if player.ads && bot.cfg.mode.auto_fire_when_aim_down_sight {
                    if let Some(LockingResult { shoot_pos, target }) = bot.ads_mode(&player, &camera, &enemies, TargetPriority::Closest) {
                        println!("ADS-AUTO-FIRE {:?} {:?} {}", target.name, shoot_pos, target.distance_to(&player));
                        LAST_SHOOT_TIME = current_time;
                    }
                }
            }
        }

        let elapsed = current_time.duration_since(last_frame_time);
        if elapsed < target_frame_time {
            std::thread::sleep(target_frame_time - elapsed);
        }
        last_frame_time = current_time;
    }
}

fn try_toggle_ads(player: &Player) -> bool {
    (Instant::now().elapsed().as_secs() % 4) < 1 && player.is_alive()
}

fn is_fire_pressed() -> bool {
    (Instant::now().elapsed().as_millis() % 1000) < 100
}