use cxx::{type_id, ExternType};
use std::mem::MaybeUninit;
#[cxx::bridge]
mod ffi {
    unsafe extern "C++" {
        include!("cxx-qt-lib/qvariant.h");
        type QVariant = super::QVariant;
        fn clear(self: &mut QVariant);
        #[rust_name = "is_null"]
        fn isNull(self: &QVariant) -> bool;
        #[rust_name = "is_valid"]
        fn isValid(self: &QVariant) -> bool;
    }
    #[namespace = "rust::cxxqtlib1"]
    unsafe extern "C++" {
        include!("cxx-qt-lib/common.h");
        #[doc(hidden)]
        #[rust_name = "qvariant_drop"]
        fn drop(variant: &mut QVariant);
        #[doc(hidden)]
        #[rust_name = "qvariant_default"]
        fn construct() -> QVariant;
        #[doc(hidden)]
        #[rust_name = "qvariant_clone"]
        fn construct(variant: &QVariant) -> QVariant;
        #[doc(hidden)]
        #[rust_name = "qvariant_eq"]
        fn operatorEq(a: &QVariant, b: &QVariant) -> bool;
    }
}
#[repr(C)]
pub struct QVariant {
    _data: MaybeUninit<f64>,
    #[cfg(qt_version_major = "5")]
    _type: MaybeUninit<u16>,
    #[cfg(qt_version_major = "5")]
    _is_shared: MaybeUninit<u16>,
    #[cfg(qt_version_major = "5")]
    _is_null: MaybeUninit<u16>,
    #[cfg(qt_version_major = "6")]
    _is_shared: MaybeUninit<usize>,
    #[cfg(qt_version_major = "6")]
    _is_null: MaybeUninit<usize>,
    #[cfg(qt_version_major = "6")]
    _packed_type: MaybeUninit<usize>,
}
impl Clone for QVariant {
    fn clone(&self) -> Self {
        ffi::qvariant_clone(self)
    }
}
impl Default for QVariant {
    fn default() -> Self {
        ffi::qvariant_default()
    }
}
impl Drop for QVariant {
    fn drop(&mut self) {
        ffi::qvariant_drop(self)
    }
}
impl<T> From<&T> for QVariant
where
    T: QVariantValue,
{
    fn from(value: &T) -> Self {
        T::construct(value)
    }
}
impl QVariant {
    pub fn value<T: QVariantValue>(&self) -> Option<T> {
        if T::can_convert(self) {
            Some(T::value_or_default(self))
        } else {
            None
        }
    }
    pub fn value_or_default<T: QVariantValue>(&self) -> T {
        T::value_or_default(self)
    }
}
impl std::cmp::PartialEq for QVariant {
    fn eq(&self, other: &Self) -> bool {
        ffi::qvariant_eq(self, other)
    }
}
pub trait QVariantValue {
    fn can_convert(variant: &QVariant) -> bool;
    fn construct(value: &Self) -> QVariant;
    fn value_or_default(variant: &QVariant) -> Self;
}
macro_rules! impl_qvariant_value {
    ( $typeName:ty, $module:ident ) => {
        mod $module;
        impl QVariantValue for $typeName {
            fn can_convert(variant: &QVariant) -> bool {
                $module::can_convert(variant)
            }
            fn construct(value: &Self) -> QVariant {
                $module::construct(value)
            }
            fn value_or_default(variant: &QVariant) -> Self {
                $module::value_or_default(variant)
            }
        }
    };
}
impl_qvariant_value!(bool, qvariant_bool);
impl_qvariant_value!(f32, qvariant_f32);
impl_qvariant_value!(f64, qvariant_f64);
impl_qvariant_value!(i8, qvariant_i8);
impl_qvariant_value!(i16, qvariant_i16);
impl_qvariant_value!(i32, qvariant_i32);
impl_qvariant_value!(i64, qvariant_i64);
impl_qvariant_value!(crate::QByteArray, qvariant_qbytearray);
#[cfg(feature = "qt_gui")]
impl_qvariant_value!(crate::QColor, qvariant_qcolor);
impl_qvariant_value!(crate::QDate, qvariant_qdate);
#[cfg(not(target_os = "emscripten"))]
impl_qvariant_value!(crate::QDateTime, qvariant_qdatetime);
impl_qvariant_value!(crate::QModelIndex, qvariant_qmodelindex);
impl_qvariant_value!(crate::QPersistentModelIndex, qvariant_qpersistentmodelindex);
impl_qvariant_value!(crate::QPoint, qvariant_qpoint);
impl_qvariant_value!(crate::QPointF, qvariant_qpointf);
impl_qvariant_value!(crate::QRect, qvariant_qrect);
impl_qvariant_value!(crate::QRectF, qvariant_qrectf);
impl_qvariant_value!(crate::QSize, qvariant_qsize);
impl_qvariant_value!(crate::QSizeF, qvariant_qsizef);
impl_qvariant_value!(crate::QString, qvariant_qstring);
impl_qvariant_value!(crate::QStringList, qvariant_qstringlist);
impl_qvariant_value!(crate::QTime, qvariant_qtime);
impl_qvariant_value!(crate::QUrl, qvariant_qurl);
impl_qvariant_value!(u8, qvariant_u8);
impl_qvariant_value!(u16, qvariant_u16);
impl_qvariant_value!(u32, qvariant_u32);
impl_qvariant_value!(u64, qvariant_u64);
unsafe impl ExternType for QVariant {
    type Id = type_id!("QVariant");
    type Kind = cxx::kind::Trivial;
}