use gtk::pango;

use super::{Attr, Formatted, FormattedSlice, Style};

pub trait ToGtkLabel {
    fn apply_to_label(&self, label: &gtk::Label, dark: bool);

    fn to_label(&self, dark: bool) -> gtk::Label {
        let label = gtk::Label::builder()
            .halign(gtk::Align::Start)
            .build();
        self.apply_to_label(&label, dark);
        label
    }
}

impl Attr {
    fn to_pango_attribute(&self, len: usize, dark: bool) -> pango::Attribute {
        let mut attr: pango::Attribute = match self.style {
            Style::Highlight => if dark {
                pango::AttrColor::new_background(0x3000, 0x0000, 0x0000).into()
            } else {
                pango::AttrColor::new_background(0xffff, 0xdfff, 0xdfff).into()
            },
            Style::Color(color) => pango::AttrColor::new_foreground(
                (((color & 0xff0000) >> 16) as u16) << 8,
                (((color & 0x00ff00) >> 8) as u16) << 8,
                ((color & 0x0000ff) as u16) << 8,
            ).into(),
            Style::Italic => pango::AttrInt::new_style(pango::Style::Italic).into(),
            Style::Monospace => pango::AttrString::new_family("monospace").into(),
            Style::Strikethrough => pango::AttrInt::new_strikethrough(true).into(),
        };
        attr.set_start_index(self.start as u32);
        let end = match self.end {
            Some(end) => end,
            None => len,
        };
        attr.set_end_index(end as u32);
        attr
    }
}

impl<'a> FormattedSlice<'a> {
    fn to_pango_attr_list(&self, dark: bool) -> Option<pango::AttrList> {
        if self.attrs.is_empty() {
            return None;
        }
        let len = self.text.len();
        let list = pango::AttrList::new();
        for attr in self.attrs.iter() {
            list.insert(attr.to_pango_attribute(len, dark));
        }
        Some(list)
    }
}

impl ToGtkLabel for Formatted {
    fn apply_to_label(&self, label: &gtk::Label, dark: bool) {
        label.set_label(&self.text);
        label.set_attributes(self.as_slice().to_pango_attr_list(dark).as_ref());
    }
}

impl<'a> ToGtkLabel for FormattedSlice<'a> {
    fn apply_to_label(&self, label: &gtk::Label, dark: bool) {
        label.set_label(&self.text);
        label.set_attributes(self.to_pango_attr_list(dark).as_ref());
    }
}
