use crate::Enemy;
use fyrox::{
    asset::manager::ResourceManager,
    core::{
        algebra::{Vector2, Vector3},
        impl_component_provider,
        math::Rect,
        reflect::prelude::*,
        sstorage::ImmutableString,
        uuid_provider,
        visitor::prelude::*,
    },
    generic_animation::spritesheet::{ImageParameters, SpriteSheetAnimation},
    material::{shader::SamplerFallback, Material, MaterialResource, PropertyValue},
    resource::texture::Texture,
    scene::{
        base::BaseBuilder,
        collider::InteractionGroups,
        dim2::{
            collider::{CapsuleShape, ColliderBuilder, ColliderShape},
            rectangle::RectangleBuilder,
            rigidbody::RigidBodyBuilder,
        },
        graph::Graph,
        rigidbody::RigidBodyType,
        transform::TransformBuilder,
    },
    script::{Script, ScriptContext, ScriptTrait},
};

impl_component_provider!(EnemySpawn,);
uuid_provider!(EnemySpawn = "b5671d19-9f1a-4286-8486-add4ebaadaec");
#[derive(Visit, Reflect, Debug, Clone, Default)]
pub struct EnemySpawn {
    x: f32,
    y: f32,
    enemy: Enemy,
}
impl EnemySpawn {
    pub fn new() -> Self {
        return  EnemySpawn::default();
    }


    fn block_anmation(&self, resource_manager: &ResourceManager) -> SpriteSheetAnimation<fyrox::asset::Resource<Texture>> {
        let idle = resource_manager.request::<Texture>(
            "assets/data/characters/skeleton/Skeleton_Warrior/Protect.png".to_owned(),
        );
        let mut idle_animation = SpriteSheetAnimation::new_from_image_parameters(ImageParameters {
            width: 128,
            height: 128,
            frame_width: 128,
            frame_height: 128,
            first_frame: 0,
            last_frame: 1,
            column_major: false,
        });
        idle_animation.set_texture(Some(idle));
        idle_animation.set_looping(false);
        idle_animation.set_speed(20.);
        idle_animation.play();
        return idle_animation;
    }

    fn attack_anmation(&self, resource_manager: &ResourceManager) -> SpriteSheetAnimation<fyrox::asset::Resource<Texture>> {
        let idle = resource_manager.request::<Texture>(
            "assets/data/characters/skeleton/Skeleton_Warrior/Attack_3.png".to_owned(),
        );
        let mut idle_animation = SpriteSheetAnimation::new_from_image_parameters(ImageParameters {
            width: 512,
            height: 128,
            frame_width: 128,
            frame_height: 128,
            first_frame: 0,
            last_frame: 6,
            column_major: false,
        });
        idle_animation.set_texture(Some(idle));
        idle_animation.set_looping(true);
        idle_animation.set_speed(20.);
        idle_animation.play();
        return idle_animation;
    }

    fn run_anmation(&self, resource_manager: &ResourceManager) -> SpriteSheetAnimation<fyrox::asset::Resource<Texture>> {
        let idle = resource_manager.request::<Texture>(
            "assets/data/characters/skeleton/Skeleton_Warrior/Run.png".to_owned(),
        );
        let mut idle_animation = SpriteSheetAnimation::new_from_image_parameters(ImageParameters {
            width: 1024,
            height: 128,
            frame_width: 128,
            frame_height: 128,
            first_frame: 0,
            last_frame: 8,
            column_major: false,
        });
        idle_animation.set_texture(Some(idle));
        idle_animation.set_looping(true);
        idle_animation.set_speed(10.);
        idle_animation.play();
        return idle_animation;
    }

    fn die_anmation(&self, resource_manager: &ResourceManager) -> SpriteSheetAnimation<fyrox::asset::Resource<Texture>> {
        let idle = resource_manager.request::<Texture>(
            "assets/data/characters/skeleton/Skeleton_Warrior/Dead.png".to_owned(),
        );
        let mut idle_animation = SpriteSheetAnimation::new_from_image_parameters(ImageParameters {
            width: 512,
            height: 128,
            frame_width: 128,
            frame_height: 128,
            first_frame: 0,
            last_frame: 4,
            column_major: false,
        });
        idle_animation.set_texture(Some(idle));
        idle_animation.set_looping(false);
        idle_animation.set_speed(10.);
        idle_animation.play();
        return idle_animation;
    }

    fn idle_anmation(&self, resource_manager: &ResourceManager) -> SpriteSheetAnimation<fyrox::asset::Resource<Texture>> {
        let idle = resource_manager.request::<Texture>(
            "assets/data/characters/skeleton/Skeleton_Warrior/Idle.png".to_owned(),
        );
        let mut idle_animation = SpriteSheetAnimation::new_from_image_parameters(ImageParameters {
            width: 896,
            height: 128,
            frame_width: 128,
            frame_height: 128,
            first_frame: 0,
            last_frame: 7,
            column_major: false,
        });
        idle_animation.set_texture(Some(idle));
        idle_animation.set_looping(true);
        idle_animation.set_speed(10.);
        idle_animation.play();
        return idle_animation;
    }

    pub fn spawn_enemy(&self, graph: &mut Graph, resource_manager: &ResourceManager, x: f32) {
        // TODO: add with_build
        let mut enemy = Enemy::default();
        enemy.x = x;
        enemy.y = -3.0;
        let x = enemy.x;
        let y = enemy.y;
        let mut material = Material::standard_2d();
        enemy.animations = vec![
            self.idle_anmation(resource_manager),
            self.run_anmation(resource_manager),
            self.attack_anmation(resource_manager),
            self.die_anmation(resource_manager),
            self.block_anmation(resource_manager),
        ];
        material
            .set_property(
                &ImmutableString::new("diffuseTexture"),
                PropertyValue::Sampler {
                    value: None,
                    fallback: SamplerFallback::Normal,
                },
            )
            .unwrap();
        let shape = ColliderShape::Capsule(CapsuleShape {
            begin: Vector2::new(0.0, -0.80),
            end: Vector2::new(0.0, -0.35),
            radius: 0.2,
        });
        let rb_transform = TransformBuilder::new()
            .with_local_position(Vector3::new(x, y, 0.0))
            .with_local_scale(Vector3::new(2.0, 2.0, 1.0))
            .build();

        RigidBodyBuilder::new(
            BaseBuilder::new()
                .with_children(&[
                    // Collider to prevent player from moving past boundary
                    RectangleBuilder::new(BaseBuilder::new())
                        .with_material(MaterialResource::new_ok(Default::default(), material))
                        // Sprite is located in top left corner of sprite sheet
                        .with_uv_rect(Rect::new(0.0, 0.3, 0.13, 0.8))
                        .build(graph),
                    ColliderBuilder::new(BaseBuilder::new())
                        .with_shape(shape)
                        .with_collision_groups(InteractionGroups::default())
                        .with_solver_groups(InteractionGroups::default())
                        .build(graph),
                ])
                // Optional, set name of tile
                .with_name(format!("Sceleton ({x}, {y})",))
                // Set position of tile
                .with_local_transform(rb_transform)
                .with_script(Script::new(enemy)),
        )
        .with_mass(100.0)
        // Turn off gravity for tile
        .with_gravity_scale(1.)
        .with_lin_damping(0.0)
        // Set tile to be static and not rotate
        .with_rotation_locked(true)
        .with_body_type(RigidBodyType::Dynamic)
        .build(graph);
    }
}
impl ScriptTrait for EnemySpawn {
    fn on_init(&mut self, context: &mut ScriptContext) {
        let resource_manager: &ResourceManager = &context.resource_manager;
        self.spawn_enemy(&mut context.scene.graph, resource_manager, 0.0);
        // self.enemy.on_init(context);
    }
}
