use std::time::Duration;

use bevy::{asset::ChangeWatcher, prelude::*, sprite::MaterialMesh2dBundle};

const SCALE: f32 = 80.0;

fn main() {
    App::new()
        .add_plugins((DefaultPlugins
            .set(ImagePlugin::default_nearest())
            .set(WindowPlugin {
                primary_window: Some(Window {
                    title: "2D Sprites".into(),
                    resolution: (640., 480.).into(),
                    ..default()
                }),
                ..default()
            })
            .set(AssetPlugin {
                watch_for_changes: ChangeWatcher::with_delay(Duration::from_millis(200)),
                ..default()
            }),))
        .add_systems(Startup, (initialize_camera, load_spritesheet))
        .add_systems(Update, initialize_board.run_if(check_initialize_board))
        .run();
}

/// Sprite sheet Resource for later reference
#[derive(Debug, Resource)]
struct SpriteSheet {
    handle: Handle<TextureAtlas>,
}

// Marker component for the 2d board entity
#[derive(Debug, Component)]
struct Board2d;

#[derive(Debug, Component)]
struct BoardIndex {
    x: usize,
    y: usize,
}

/// STARTUP: Initialize 2d gameplay Camera
fn initialize_camera(mut commands: Commands) {
    commands.spawn(Camera2dBundle::default());
}

/// STARTUP: Load sprite sheet and insert texture atlas
fn load_spritesheet(
    mut texture_atlases: ResMut<Assets<TextureAtlas>>,
    server: Res<AssetServer>,
    mut commands: Commands,
) {
    let atlas = TextureAtlas::from_grid(
        server.load("sprites.png"),
        Vec2::new(16.0, 16.0),
        5,
        1,
        None,
        None,
    );
    commands.insert_resource(SpriteSheet {
        handle: texture_atlases.add(atlas),
    });
}

fn check_initialize_board(query: Query<Entity, With<Board2d>>) -> bool {
    query.is_empty()
}

/// STARTUP: Initialize the board for representation
fn initialize_board(sprite_sheet: Option<Res<SpriteSheet>>, mut commands: Commands) {
    if let Some(sprite_sheet) = sprite_sheet {
        commands
            .spawn((
                SpatialBundle {
                    transform: Transform::from_xyz(-SCALE * 3.5, -SCALE * 1.5, 0.0),
                    ..default()
                },
                Board2d,
            ))
            .with_children(|parent| {
                for i in 0..32 {
                    let x = i % 8;
                    let y = i / 8;
                    let s = (x % 2) ^ (y % 2);

                    let transform = Transform::from_scale(Vec3::splat(5.0))
                        .with_translation(Vec3::new(SCALE * x as f32, SCALE * y as f32, 0.0));

                    let sprite = TextureAtlasSprite::new(s);

                    let texture_atlas = sprite_sheet.handle.clone();

                    let index = BoardIndex { x, y };

                    // Rectangle
                    parent.spawn((
                        SpriteSheetBundle {
                            texture_atlas,
                            sprite,
                            transform,
                            ..default()
                        },
                        index,
                    ));
                }
            });
    }
}
