//! GLib interfaces.

use glib_sys::*;
use gobject_sys::*;
use maraiah::durandal::ffi;
use std::marker::PhantomData;

impl<T> std::ops::Deref for Refc<'_, T>
{
   type Target = *mut T;

   fn deref(&self) -> &Self::Target {&self.p}
}

impl<T> Drop for Refc<'_, T>
{
   fn drop(&mut self)
   {
      unsafe {
         g_object_unref(self.p as _);
      }
   }
}

impl<T> Refc<'_, T>
{
   /// Creates a new `Refc` which will own an already referenced object.
   pub const fn new(p: *mut T) -> Self {Self{p, l: PhantomData}}

   /// Creates a new `Refc` which will hold a reference to the object.
   pub fn own(p: *mut T) -> Self {unsafe {g_object_ref(p as _);} Self::new(p)}
}

impl ListD
{
   pub fn new(head: *mut GList) -> Self {Self{head, iter: head}}
}

impl Iterator for ListD
{
   type Item = gpointer;

   fn next(&mut self) -> Option<gpointer> {
      if self.iter != ffi::null_mut() {
         let obj = unsafe {
            let obj = (*self.iter).data;
            self.iter = (*self.iter).next;
            obj
         };

         Some(obj)
      } else {
         None
      }
   }
}

impl Drop for ListD
{
   fn drop(&mut self) {unsafe {g_list_free(self.head);}}
}

impl ListS
{
   pub fn new(head: *mut GSList) -> Self {Self{head, iter: head}}
}

impl Iterator for ListS
{
   type Item = gpointer;

   fn next(&mut self) -> Option<gpointer> {
      if self.iter != ffi::null_mut() {
         let obj = unsafe {
            let obj = (*self.iter).data;
            self.iter = (*self.iter).next;
            obj
         };

         Some(obj)
      } else {
         None
      }
   }
}

impl Drop for ListS
{
   fn drop(&mut self) {unsafe {g_slist_free(self.head);}}
}

/// A GObject owned pointer.
pub struct Refc<'a, T>
{
   p: *mut T,
   l: PhantomData<&'a *mut T>,
}

/// A GList wrapper.
pub struct ListD
{
   head: *mut GList,
   iter: *mut GList,
}

/// A GSList wrapper.
pub struct ListS
{
   head: *mut GSList,
   iter: *mut GSList,
}

// EOF
