use crate::utilities;
use cairo::Context;
use gtk::gdk_pixbuf::Pixbuf;
use image::DynamicImage;

#[derive(Clone, Debug)]
pub enum Terrain {
    Badlands,
    DeepWater,
    Desert,
    Empty,
    Grasslands,
    Mountain,
    ShallowWater,
    Swamp,
}

impl Default for Terrain {
    fn default() -> Self {
        Self::Empty
    }
}

impl From<&str> for Terrain {
    fn from(s: &str) -> Self {
        match s {
            "m" => Self::Mountain,
            "g" => Self::Grasslands,
            "sw" => Self::ShallowWater,
            "dw" => Self::DeepWater,
            "b" => Self::Badlands,
            "d" => Self::Desert,
            "s" => Self::Swamp,
            _ => Self::Empty,
        }
    }
}

impl From<String> for Terrain {
    fn from(s: String) -> Self {
        Self::from(s.as_ref())
    }
}

impl From<&Terrain> for String {
    fn from(t: &Terrain) -> Self {
        match t {
            Terrain::Badlands => "Badlands",
            Terrain::DeepWater => "Deep Water",
            Terrain::Desert => "Desert",
            Terrain::Empty => "Empty",
            Terrain::Grasslands => "Grasslands",
            Terrain::Mountain => "Mountain",
            Terrain::ShallowWater => "Shallow Water",
            Terrain::Swamp => "Swamp",
        }
        .to_owned()
    }
}

pub struct Tile {
    pub terrain: Terrain,
    pub image: Pixbuf,
}

impl Tile {
    pub fn new(source: &DynamicImage, terrain: Terrain) -> Tile {
        let image = match terrain {
            Terrain::DeepWater => pixbuf_from_image_tile(source.clone().crop(0, 0, 100, 88)),
            Terrain::ShallowWater => pixbuf_from_image_tile(source.clone().crop(100, 0, 100, 88)),
            Terrain::Grasslands => pixbuf_from_image_tile(source.clone().crop(200, 0, 100, 88)),
            Terrain::Desert => pixbuf_from_image_tile(source.clone().crop(300, 0, 100, 88)),
            Terrain::Mountain => pixbuf_from_image_tile(source.clone().crop(0, 88, 100, 88)),
            Terrain::Badlands => pixbuf_from_image_tile(source.clone().crop(100, 88, 100, 88)),
            Terrain::Swamp => pixbuf_from_image_tile(source.clone().crop(0, 176, 100, 88)),
            Terrain::Empty => pixbuf_from_image_tile(source.clone().crop(300, 176, 100, 88)),
        };

        Tile { terrain, image }
    }

    pub fn render_on_context(&self, context: &Context, translate_x: f64, translate_y: f64) {
        context.save().unwrap();
        context.append_path(&utilities::hexagon_path(
            context,
            translate_x,
            translate_y,
            100.,
            88.,
        ));
        context.clip();
        // panic!("content.set_source_pixbuf got deprecated and I haven't figured out the replacement yet.");
        // context.set_source_pixbuf(&self.image, translate_x, translate_y);
        context.paint().expect("paint should succeed");
        context.restore().unwrap();
    }
}

fn pixbuf_from_image_tile(image: image::DynamicImage) -> Pixbuf {
    Pixbuf::from_bytes(
        &glib::Bytes::from(image.as_bytes()),
        gtk::gdk_pixbuf::Colorspace::Rgb,
        false,
        8,
        image.width() as i32,
        image.height() as i32,
        image.to_rgb8().sample_layout().height_stride as i32,
    )
}
