use std::{borrow::Cow, collections::HashMap, ffi::c_void, marker::PhantomData};
use crate::{buffer::Buffer, Weechat};
use weechat_sys::{t_hdata, t_weechat_plugin};
pub struct BufferLines<'a> {
pub(crate) weechat_ptr: *mut t_weechat_plugin,
pub(crate) first_line: *mut c_void,
pub(crate) last_line: *mut c_void,
pub(crate) buffer: PhantomData<&'a Buffer<'a>>,
pub(crate) done: bool,
}
impl<'a> Iterator for BufferLines<'a> {
type Item = BufferLine<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.done {
None
} else {
let weechat = Weechat::from_ptr(self.weechat_ptr);
let line_hdata = unsafe { weechat.hdata_get("line") };
let line_data_pointer =
unsafe { weechat.hdata_pointer(line_hdata, self.first_line, "data") };
if line_data_pointer.is_null() {
return None;
}
if self.first_line == self.last_line {
self.done = true;
}
self.first_line = unsafe { weechat.hdata_move(line_hdata, self.first_line, 1) };
Some(BufferLine {
weechat,
line_data_pointer,
buffer: PhantomData,
})
}
}
}
impl<'a> DoubleEndedIterator for BufferLines<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.done {
None
} else {
let weechat = Weechat::from_ptr(self.weechat_ptr);
let line_hdata = unsafe { weechat.hdata_get("line") };
let line_data_pointer =
unsafe { weechat.hdata_pointer(line_hdata, self.last_line, "data") };
if line_data_pointer.is_null() {
return None;
}
if self.last_line == self.first_line {
self.done = true;
}
self.last_line = unsafe { weechat.hdata_move(line_hdata, self.last_line, -1) };
Some(BufferLine {
weechat,
line_data_pointer,
buffer: PhantomData,
})
}
}
}
#[allow(missing_docs)]
#[derive(Debug, Clone, Default)]
pub struct LineData<'a> {
pub prefix: Option<&'a str>,
pub message: Option<&'a str>,
pub date: Option<i64>,
pub date_printed: Option<i64>,
pub tags: Option<&'a [&'a str]>,
}
pub struct BufferLine<'a> {
weechat: Weechat,
line_data_pointer: *mut c_void,
buffer: PhantomData<&'a Buffer<'a>>,
}
impl<'a> BufferLine<'a> {
fn hdata(&self) -> *mut t_hdata {
unsafe { self.weechat.hdata_get("line_data") }
}
fn update_line(&self, hashmap: HashMap<&str, &str>) {
unsafe {
self.weechat
.hdata_update(self.hdata(), self.line_data_pointer, hashmap);
}
}
pub fn prefix(&self) -> Cow<str> {
unsafe {
self.weechat
.hdata_string(self.hdata(), self.line_data_pointer, "prefix")
}
}
pub fn set_prefix(&self, new_prefix: &str) {
let mut hashmap = HashMap::new();
hashmap.insert("prefix", new_prefix);
self.update_line(hashmap);
}
pub fn message(&self) -> Cow<str> {
unsafe {
self.weechat
.hdata_string(self.hdata(), self.line_data_pointer, "message")
}
}
pub fn set_message(&self, new_value: &str) {
let mut hashmap = HashMap::new();
hashmap.insert("message", new_value);
self.update_line(hashmap);
}
pub fn date(&self) -> i64 {
unsafe {
self.weechat
.hdata_time(self.hdata(), self.line_data_pointer, "date")
}
}
pub fn set_date(&self, new_value: i64) {
let mut hashmap = HashMap::new();
let date = new_value.to_string();
hashmap.insert("date", date.as_ref());
self.update_line(hashmap);
}
pub fn date_printed(&self) -> i64 {
unsafe {
self.weechat
.hdata_time(self.hdata(), self.line_data_pointer, "date_printed")
}
}
pub fn set_date_printed(&self, new_value: &str) {
let mut hashmap = HashMap::new();
let date = new_value.to_string();
hashmap.insert("date_printed", date.as_ref());
self.update_line(hashmap);
}
pub fn highlighted(&self) -> bool {
unsafe {
self.weechat
.hdata_char(self.hdata(), self.line_data_pointer, "highlight")
!= 0
}
}
pub fn tags(&self) -> Vec<Cow<str>> {
unsafe {
let count = self.weechat.hdata_var_array_size(
self.hdata(),
self.line_data_pointer,
"tags_array",
);
let mut tags = Vec::with_capacity(count as usize);
for i in 0..count {
let tag = self.weechat.hdata_string(
self.hdata(),
self.line_data_pointer,
&format!("{}|tags_array", i),
);
tags.push(tag);
}
tags
}
}
pub fn set_tags(&self, new_value: &[&str]) {
let mut hashmap = HashMap::new();
let tags = new_value.join(",");
hashmap.insert("tags_array", tags.as_ref());
self.update_line(hashmap);
}
pub fn update(&self, data: LineData<'a>) {
let mut hashmap = HashMap::new();
let tags = data.tags.map(|t| t.join(","));
let date = data.date.map(|d| d.to_string());
let date_printed = data.date_printed.map(|d| d.to_string());
if let Some(message) = data.message {
hashmap.insert("message", message);
}
if let Some(prefix) = data.prefix {
hashmap.insert("prefix", prefix);
}
if let Some(t) = tags.as_ref() {
hashmap.insert("tags_array", t);
}
if let Some(d) = date.as_ref() {
hashmap.insert("date", d);
}
if let Some(d) = date_printed.as_ref() {
hashmap.insert("date_printed", d);
}
self.update_line(hashmap);
}
}