use crate::canvas::canvas_state::{Drawable, CanvasTextureHandle, CanvasImageHandle};
use std::sync::Arc;

#[derive(Debug, Clone)]
pub struct Sprite {

    pub vertices: [(f32, f32, f32); 6],
    pub ti_position: [(f32, f32); 6],

    position: (f32, f32),
    size: (f32, f32),
    color: (f32, f32, f32, f32),

    textured: bool,
    texture_handle: Option<Arc<CanvasTextureHandle>>,

}

/// Container class which implements drawable.
impl Sprite {

    pub fn new(position: (f32, f32), size: (f32, f32)) -> Sprite {
        Sprite::new_with_color(position, size, 0, (0.,0.,0.,0.))
    }

    pub fn new_with_color(position: (f32, f32),
                          size: (f32, f32),
                          depth: u32,
                          color: (f32, f32, f32, f32)) -> Sprite {

        let normalized_depth = (depth as f32 / 255.0);

        Sprite {
            vertices: [
                (position.0, position.1                  , normalized_depth),    // top left
                (position.0, position.1 + size.1         , normalized_depth),    // bottom left
                (position.0 + size.0, position.1 + size.1, normalized_depth),    // bottom right
                (position.0, position.1                  , normalized_depth),    // top left
                (position.0 + size.0, position.1 + size.1, normalized_depth),    // bottom right
                (position.0 + size.0, position.1         , normalized_depth),    // top right
            ],

            position: position,
            ti_position: [
                (-0.0, -0.0),          // top left
                (-0.0,  1.0),          // bottom left
                ( 1.0,  1.0),          // bottom right
                (-0.0, -0.0),          // top left
                ( 1.0,  1.0),          // bottom right
                ( 1.0, -0.0),          // top right
            ],
            size: size,
            color: color,
            textured: false,
            texture_handle: None
        }
    }

    ///
    pub fn new_with_texture(position: (f32, f32),
                            size: (f32, f32),
                            depth: u32,
                            texture_handle: Arc<CanvasTextureHandle>) -> Sprite {

        let normalized_depth = (depth as f32 / 255.0);

        Sprite {
            vertices: [
                (position.0, position.1                  , normalized_depth),    // top left
                (position.0, position.1 + size.1         , normalized_depth),    // bottom left
                (position.0 + size.0, position.1 + size.1, normalized_depth),    // bottom right
                (position.0, position.1                  , normalized_depth),    // top left
                (position.0 + size.0, position.1 + size.1, normalized_depth),    // bottom right
                (position.0 + size.0, position.1         , normalized_depth),    // top right
            ],
            position: position,
            ti_position: [
                (-0.0, -0.0),          // top left
                (-0.0,  1.0),          // bottom left
                ( 1.0,  1.0),          // bottom right
                (-0.0, -0.0),          // top left
                ( 1.0,  1.0),          // bottom right
                ( 1.0, -0.0),          // top right
            ],
            size: size,
            color: (1.0, 0.0, 0.0, 1.0),
            textured: true,
            texture_handle: Some(texture_handle.clone())
        }
    }



}

impl Drawable for Sprite {

    fn get_vertices(&self) -> Vec<(f32,f32,f32)> {
        self.vertices.to_vec()
    }

    fn get_color(&self) -> (f32, f32, f32, f32) {
        self.color.clone()
    }

    fn get_ti_coords(&self) -> Vec<(f32, f32)> {
        self.ti_position.to_vec()
    }

    fn get_texture_handle(&self) -> Option<Arc<CanvasTextureHandle>> {
        match self.textured {
            true => {
                self.texture_handle.clone()
            },
            false => None,
        }
    }

    fn get_image_handle(&self) -> Option<Arc<CanvasImageHandle>> {
        None
    }
}


#[derive(Debug, Clone)]
pub struct Poly {

    pub vertices: Vec<(f32, f32, f32)>,
    pub ti_position: Vec<(f32, f32)>,

    position: (f32, f32),
    size: (f32, f32),
    color: (f32, f32, f32, f32),

    textured: bool,
    texture_handle: Option<Arc<CanvasTextureHandle>>,

}

/// Container class which implements drawable.
impl Poly {

    pub fn new(position: (f32, f32), size: (f32, f32)) -> Poly {
        Poly::new_with_color(position, size, 0, (0.,0.,0.,0.))
    }

    pub fn new_with_color(position: (f32, f32),
                          size: (f32, f32),
                          depth: u32,
                          color: (f32, f32, f32, f32)) -> Poly {

        let normalized_depth = (depth as f32 / 255.0);

        Poly {
            vertices: vec![
                (-0.5   ,   -0.5    ,    normalized_depth),
                (-1.0   ,   1.0     ,    normalized_depth),
                (-0.25  ,   0.0     ,    normalized_depth),

                (-0.25  ,   0.0     ,    normalized_depth),
                (-1.0   ,   1.0     ,    normalized_depth),
                (0.0    ,   0.5     ,    normalized_depth),

                (0.25   ,   0.0     ,    normalized_depth),
                (-1.0   ,   1.0     ,    normalized_depth),
                (0.0    ,   0.5     ,    normalized_depth),

                (0.5    ,   -0.5    ,    normalized_depth),
                (-1.0   ,   1.0     ,    normalized_depth),
                (0.25   ,   0.0     ,    normalized_depth),

                (0.25   ,   -0.5    ,    normalized_depth),
                (-1.0   ,   1.0     ,    normalized_depth),
                (0.5    ,   -0.5    ,    normalized_depth),

                (0.25   ,   -0.5    ,    normalized_depth),
                (-1.0   ,   1.0     ,    normalized_depth),
                (0.0    ,   -0.1    ,    normalized_depth),

                (-0.25  ,   -0.5    ,    normalized_depth),
                (-1.0   ,   1.0     ,    normalized_depth),
                (0.0    ,   -0.1    ,    normalized_depth),

                (-0.5   ,   -0.5    ,    normalized_depth),
                (-1.0   ,   1.0     ,    normalized_depth),
                (-0.25  ,   -0.5    ,    normalized_depth),
            ],

            position: position,
            ti_position: vec![
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
                (0.0,0.0),
            ],
            size: size,
            color: color,
            textured: false,
            texture_handle: None
        }
    }
}

impl Drawable for Poly {

    fn get_vertices(&self) -> Vec<(f32,f32,f32)> {
        self.vertices.to_vec()
    }

    fn get_color(&self) -> (f32, f32, f32, f32) {
        self.color.clone()
    }

    fn get_ti_coords(&self) -> Vec<(f32, f32)> {
        self.ti_position.to_vec()
    }

    fn get_texture_handle(&self) -> Option<Arc<CanvasTextureHandle>> {
        match self.textured {
            true => {
                self.texture_handle.clone()
            },
            false => None,
        }
    }

    fn get_image_handle(&self) -> Option<Arc<CanvasImageHandle>> {
        None
    }
}
