use bevy::{
    core_pipeline::clear_color::ClearColorConfig,
    prelude::*,
    render::{camera::RenderTarget, render_resource::*, view::RenderLayers},
};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins.set(WindowPlugin {
            primary_window: Some(Window {
                title: "Camera Image UI".into(),
                resolution: (640., 480.).into(),
                ..default()
            }),
            ..default()
        }))
        .add_startup_system(init)
        .run();
}

fn init(
    mut commands: Commands,
    mut images: ResMut<Assets<Image>>,
    mut meshes: ResMut<Assets<Mesh>>,
) {
    info!("Creating preview");

    let size = Extent3d {
        width: 512,
        height: 512,
        ..default()
    };

    // Create render target image for the preview camera
    let mut image = Image {
        texture_descriptor: TextureDescriptor {
            label: None,
            size,
            dimension: TextureDimension::D2,
            format: TextureFormat::Bgra8UnormSrgb,
            mip_level_count: 1,
            sample_count: 1,
            usage: TextureUsages::TEXTURE_BINDING
                | TextureUsages::COPY_DST
                | TextureUsages::RENDER_ATTACHMENT,
            view_formats: &[],
        },
        ..default()
    };

    // Fill with zeroes
    image.resize(size);

    let image_handle = images.add(image);

    commands
        .spawn((
            TransformBundle { ..default() },
            VisibilityBundle { ..default() },
        ))
        .with_children(|parent| {
            // Spawn preview camera
            parent.spawn((
                Camera3dBundle {
                    camera_3d: Camera3d {
                        clear_color: ClearColorConfig::Custom(Color::WHITE),
                        ..default()
                    },
                    camera: Camera {
                        order: -1,
                        target: RenderTarget::Image(image_handle.clone()),
                        ..default()
                    },
                    transform: Transform::from_xyz(2.0, 2.0, 2.0).looking_at(Vec3::ZERO, Vec3::Y),
                    ..default()
                },
                UiCameraConfig { show_ui: false },
                RenderLayers::layer(1),
            ));

            parent.spawn((
                PbrBundle {
                    mesh: meshes.add(Mesh::from(shape::Cube { size: 0.5 })),
                    transform: Transform::from_xyz(0.0, 0.0, 0.0),
                    ..default()
                },
                RenderLayers::layer(1),
            ));

            parent.spawn(PointLightBundle {
                transform: Transform::from_translation(Vec3::new(0.0, 0.0, 10.0)),
                ..default()
            });
        });

    // Assign render target image to UI element
    commands
        .spawn(NodeBundle {
            style: Style {
                size: Size::all(Val::Percent(50.0)),
                justify_content: JustifyContent::SpaceBetween,
                ..default()
            },
            ..default()
        })
        .with_children(|parent| {
            parent.spawn(ImageBundle {
                image: UiImage {
                    texture: image_handle.clone(),
                    ..default()
                },
                style: Style {
                    size: Size::all(Val::Percent(100.0)),
                    ..default()
                },
                ..default()
            });
        });

    commands.spawn((
        Camera2dBundle {
            camera_2d: Camera2d {
                clear_color: ClearColorConfig::Custom(Color::TEAL),
            },
            transform: Transform::from_xyz(2.0, 2.0, 2.0).looking_at(Vec3::ZERO, Vec3::Y),
            ..default()
        },
        RenderLayers::layer(0),
    ));
}
