use crate::math::Vec2;
use bitflags::bitflags;
use serde::{Serialize, Deserialize};
use std::fmt;

#[repr(C, align(64))]
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct Entity {
    pub id: u32,
    pub team: u8,
    pub is_player: bool,
    pub is_enemy: bool,
    pub is_alive: bool,
    pub name: [u8; 32],

    pub pos: Vec2,
    pub vel: Vec2,
    pub acc: Vec2,
    pub origin: Vec2,
    pub mins: Vec2,
    pub maxs: Vec2,
    pub abs_velocity: Vec2,
    pub size: f32,
    pub hitbox_radius: f32,
    pub rotation: f32,
    pub scale: f32,

    pub health: f32,
    pub armor_value: u8,
    pub has_helmet: bool,
    pub last_shot_time: f32,
    pub fire_rate: f32,
    pub shoot_cooldown: f32,
    pub aim_angle: f32,
    pub aim_punch: Vec2,
    pub punch_velocity: Vec2,
    pub weapon_type: WeaponType,

    pub color: [u8; 4],
    pub animation_frame: u8,
    pub animation_speed: f32,
    pub flash_alpha: f32,
    pub flash_duration: f32,
    pub flash_start_time: f32,
    pub is_flashed: bool,

    pub stance: Stance,
    pub duck_state: DuckState,
    pub prone: bool,
    pub prone_height: f32,
    pub on_ground: bool,
    pub ground_entity: u32,
    pub movement_type: MovementType,
    pub velocity_modifier: f32,
    pub gravity_scale: f32,
    pub jump_power: f32,
    pub sprint_speed: f32,
    pub crouch_speed: f32,
    pub walk_speed: f32,

    pub fov: f32,
    pub zoom_fov: f32,
    pub crosshair_pos: Vec2,
    pub view_angles: Vec2,
    pub third_person: bool,
    pub override_view: Option<OverrideView>,

    pub state: EntityState,
    pub input_flags: InputFlags,
    pub in_vehicle: bool,
    pub vehicle_id: u32,
    pub has_defuser: bool,
    pub has_bomb: bool,
    pub bomb_planted: bool,
    pub bomb_timer: f32,
    pub bomb_defusing: bool,
    pub defuse_progress: f32,
    pub defuse_time_left: f32,

    pub round_time_left: f32,
    pub round_number: u16,
    pub total_rounds_played: u16,
    pub game_mode: GameMode,
    pub map_name: [u8; 32],

    pub score: i32,
    pub kills: u16,
    pub deaths: u16,
    pub assists: u16,
    pub money: i32,

    pub ping: u16,
    pub server_ip: [u8; 16],
    pub server_port: u16,
    pub connection_quality: f32,
    pub packet_loss: f32,
    pub latency: f32,

    pub fps: f32,
    pub cpu_usage: f32,
    pub gpu_usage: f32,
    pub ram_usage: f32,
    pub vram_usage: f32,

    pub battery_level: f32,
    pub is_charging: bool,
    pub device_temperature: f32,
    pub network_type: NetworkType,
    pub signal_strength: i8,
    pub wifi_ssid: [u8; 32],
    pub wifi_rssi: i8,
    pub mobile_carrier: [u8; 32],
    pub mobile_signal: u8,

    pub touch_input: TouchInput,
    pub gyro_x: f32,
    pub gyro_y: f32,
    pub gyro_z: f32,
    pub accel_x: f32,
    pub accel_y: f32,
    pub accel_z: f32,
    pub compass_heading: f32,

    pub gps_latitude: f64,
    pub gps_longitude: f64,
    pub gps_altitude: f32,
    pub gps_accuracy: f32,

    pub jailbroken: bool,
    pub rooted: bool,
    pub debug_build: bool,
    pub dev_mode: bool,
    pub bootloader_unlocked: bool,
    pub verified_boot_state: VerifiedBootState,
    pub dm_verity_enabled: bool,
    pub force_encrypted: bool,

    pub cheat_engine_detected: bool,
    pub memory_scanner_detected: bool,
    pub debugger_attached: bool,
    pub anti_cheat_bypassed: bool,
    pub modded: bool,
    pub overlay_present: bool,
    pub screen_recording: bool,
    pub accessibility_services_enabled: bool,
    pub root_apps_installed: bool,
    pub magisk_installed: bool,
    pub xposed_installed: bool,
    pub frida_server_running: bool,
    pub ptrace_hooked: bool,
    pub hooking_library_loaded: bool,
    pub game_modified: bool,

    pub game_version: u32,
    pub patch_level: u32,
    pub build_number: u32,
    pub security_patch_level: u32,
    pub kernel_version: [u8; 64],
    pub android_version: [u8; 16],

    pub manufacturer: [u8; 32],
    pub model: [u8; 32],
    pub product: [u8; 32],
    pub serial_number: [u8; 32],

    pub data_partition_mounted: bool,
    pub system_partition_integrity: PartitionIntegrity,
    pub vendor_partition_integrity: PartitionIntegrity,
    pub odm_partition_integrity: PartitionIntegrity,
    pub product_partition_integrity: PartitionIntegrity,
    pub system_ext_partition_integrity: PartitionIntegrity,

    pub flags: EntityFlags,
    pub effects: u32,
    pub model_index: u32,
    pub sequence: u32,
    pub anim_time: f32,
    pub frame: f32,
    pub skin: u32,
    pub body: u32,
    pub hitbox_set: u32,
    pub last_update_time: f32,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum EntityState {
    Alive,
    Dead,
    Dying,
    Spawning,
    Invisible,
    Knocked,
    RespawnTimer,
    TeamSwitching,
    Spectating,
    Connecting,
    Disconnected,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum WeaponType {
    Pistol,
    Rifle,
    Shotgun,
    Sniper,
    MachineGun,
    Grenade,
    Melee,
    Throwable,
    C4,
    Unknown,
}

bitflags! {
    #[derive(Serialize, Deserialize)]
    pub struct InputFlags: u64 {
        const MOVE_FORWARD = 1 << 0;
        const MOVE_BACKWARD = 1 << 1;
        const MOVE_LEFT = 1 << 2;
        const MOVE_RIGHT = 1 << 3;
        const JUMP = 1 << 4;
        const DUCK = 1 << 5;
        const ATTACK = 1 << 6;
        const ATTACK2 = 1 << 7;
        const RELOAD = 1 << 8;
        const USE_KEY = 1 << 9;
        const SPRINT = 1 << 10;
        const CROUCH = 1 << 11;
        const PRONE = 1 << 12;
        const FLASHLIGHT = 1 << 13;
        const NIGHT_VISION = 1 << 14;
        const ZOOM = 1 << 15;
        const GRENADE_PULL_PIN = 1 << 16;
        const GRENADE_THROW = 1 << 17;
        const MELEE_ATTACK = 1 << 18;
        const LEAN_LEFT = 1 << 19;
        const LEAN_RIGHT = 1 << 20;
        const TOGGLE_THIRD_PERSON = 1 << 21;
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum Stance {
    Standing,
    Crouching,
    Prone,
    Jumping,
    Climbing,
    Swimming,
    Flying,
    Driving,
    Passenger,
    OnMount,
    OnVehicle,
    OnZipline,
    OnParachute,
    OnJetpack,
    OnTurret,
    Spectating,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum DuckState {
    NotDucking,
    StartDucking,
    FullyDucked,
    FinishDucking,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum MovementType {
    Walk,
    Sprint,
    Crawl,
    Climb,
    Swim,
    Fly,
    Drive,
    Ride,
    Glide,
    Parachute,
    Jetpack,
    Vehicle,
    Turret,
    Stationary,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum GameMode {
    Deathmatch,
    TeamDeathmatch,
    Domination,
    SearchAndDestroy,
    Conquest,
    Rush,
    BattleRoyale,
    KingOfTheHill,
    CaptureTheFlag,
    Payload,
    GunGame,
    Survival,
    ZombieSurvival,
    Campaign,
    Training,
    Custom,
    Ranked,
    Casual,
}

#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct TouchInput {
    pub is_touching: bool,
    pub touch_pos: Vec2,
    pub touch_force: f32,
    pub touch_count: u8,
}

#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct OverrideView {
    pub origin: Vec2,
    pub angles: Vec2,
    pub fov: f32,
    pub distance: f32,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum NetworkType {
    Wifi,
    Mobile2G,
    Mobile3G,
    Mobile4G,
    Mobile5G,
    Ethernet,
    None,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum VerifiedBootState {
    Verified,
    SelfSigned,
    Unverified,
    Failed,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum PartitionIntegrity {
    Intact,
    Tampered,
    Corrupted,
    Unknown,
}

bitflags! {
    #[derive(Serialize, Deserialize)]
    pub struct EntityFlags: u32 {
        const IS_BOSS = 1 << 0;
        const IS_BOT = 1 << 1;
        const IS_INVULNERABLE = 1 << 2;
        const IS_CLOAKED = 1 << 3;
        const IS_SILENCED = 1 << 4;
        const HAS_AMMO_PACK = 1 << 5;
        const HAS_HEALTH_PACK = 1 << 6;
        const IS_MARKED = 1 << 7;
    }
}

impl fmt::Display for EntityState {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

impl fmt::Display for WeaponType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

impl fmt::Display for Stance {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

impl fmt::Display for GameMode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}