use avian3d::prelude::*;
use bevy::{app::plugin_group, core_pipeline::tonemapping::Tonemapping, prelude::*};
use bevy_common_assets::ron::RonAssetPlugin;
use bevy_sprite3d::Sprite3dPlugin;
use bevy_trenchbroom::prelude::*;
use bevy_ui_gradients::UiGradientsPlugin;
use lightyear::prelude::server::ServerPlugins;
use shared::{DebugVisuals, GameState, heads_database::HeadDatabaseAsset};
use std::time::Duration;

mod backpack;
mod config;
mod player;
mod server;
mod tb_entities;
mod utils;

plugin_group! {
    pub struct DefaultPlugins {
        bevy::app:::PanicHandlerPlugin,
        bevy::log:::LogPlugin,
        bevy::app:::TaskPoolPlugin,
        bevy::diagnostic:::FrameCountPlugin,
        bevy::time:::TimePlugin,
        bevy::transform:::TransformPlugin,
        bevy::diagnostic:::DiagnosticsPlugin,
        bevy::input:::InputPlugin,
        bevy::app:::ScheduleRunnerPlugin,
        bevy::window:::WindowPlugin,
        bevy::a11y:::AccessibilityPlugin,
        bevy::app:::TerminalCtrlCHandlerPlugin,
        bevy::asset:::AssetPlugin,
        bevy::scene:::ScenePlugin,
        bevy::render:::RenderPlugin,
        bevy::render::texture:::ImagePlugin,
        bevy::render::pipelined_rendering:::PipelinedRenderingPlugin,
        bevy::core_pipeline:::CorePipelinePlugin,
        bevy::sprite:::SpritePlugin,
        bevy::text:::TextPlugin,
        bevy::ui:::UiPlugin,
        bevy::pbr:::PbrPlugin,
        bevy::gltf:::GltfPlugin,
        bevy::gilrs:::GilrsPlugin,
        bevy::animation:::AnimationPlugin,
        bevy::gizmos:::GizmoPlugin,
        bevy::state::app:::StatesPlugin,
        #[plugin_group]
        bevy::picking:::DefaultPickingPlugins,
    }
}

fn main() {
    let mut app = App::new();

    app.register_type::<DebugVisuals>()
        .register_type::<TransformInterpolation>();
    app.insert_resource(DebugVisuals {
        unlit: false,
        tonemapping: Tonemapping::None,
        exposure: 1.,
        shadows: true,
        cam_follow: true,
    });

    app.add_plugins(DefaultPlugins.set(bevy::log::LogPlugin {
        filter: "info,lightyear_replication=off".into(),
        level: bevy::log::Level::INFO,
        // provide custom log layer to receive logging events
        ..default()
    }));

    app.add_plugins(ServerPlugins {
        tick_duration: Duration::from_secs_f32(1.0 / 60.0),
    });
    app.add_plugins(PhysicsPlugins::default());
    app.add_plugins(Sprite3dPlugin);
    app.add_plugins(TrenchBroomPlugins(
        TrenchBroomConfig::new("hedz").icon(None),
    ));
    app.add_plugins(UiGradientsPlugin);
    app.add_plugins(RonAssetPlugin::<HeadDatabaseAsset>::new(&["headsdb.ron"]));

    app.add_plugins(shared::abilities::plugin);
    app.add_plugins(shared::ai::plugin);
    app.add_plugins(shared::aim::plugin);
    app.add_plugins(shared::animation::plugin);
    app.add_plugins(shared::backpack::plugin);
    app.add_plugins(shared::camera::plugin);
    app.add_plugins(shared::cash::plugin);
    app.add_plugins(shared::cash_heal::plugin);
    app.add_plugins(shared::character::plugin);
    app.add_plugins(shared::control::plugin);
    app.add_plugins(shared::cutscene::plugin);
    app.add_plugins(shared::gates::plugin);
    app.add_plugins(shared::head_drop::plugin);
    app.add_plugins(shared::heads::plugin);
    app.add_plugins(shared::hitpoints::plugin);
    app.add_plugins(shared::keys::plugin);
    app.add_plugins(shared::loading_assets::LoadingPlugin);
    app.add_plugins(shared::loading_map::plugin);
    app.add_plugins(shared::movables::plugin);
    app.add_plugins(shared::npc::plugin);
    app.add_plugins(shared::platforms::plugin);
    app.add_plugins(shared::player::plugin);
    app.add_plugins(shared::protocol::plugin);
    app.add_plugins(shared::steam::plugin);
    app.add_plugins(shared::tb_entities::plugin);
    app.add_plugins(shared::utils::auto_rotate::plugin);
    app.add_plugins(shared::utils::billboards::plugin);
    app.add_plugins(shared::utils::explosions::plugin);
    app.add_plugins(shared::utils::sprite_3d_animation::plugin);
    app.add_plugins(shared::utils::squish_animation::plugin);
    app.add_plugins(shared::utils::trail::plugin);
    app.add_plugins(shared::utils::plugin);
    app.add_plugins(shared::water::plugin);

    app.add_plugins(backpack::plugin);
    app.add_plugins(config::plugin);
    app.add_plugins(player::plugin);
    app.add_plugins(server::plugin);
    app.add_plugins(tb_entities::plugin);
    app.add_plugins(utils::plugin);

    app.init_state::<GameState>();

    app.add_systems(PostStartup, setup_panic_handler);

    app.run();
}

fn setup_panic_handler() {
    _ = std::panic::take_hook();
}
