use serde::{Deserialize, Serialize};
use std::ops::{Deref, DerefMut};
use ts_rs::TS;

pub use magnetar_mmm_parser as mmm;
pub mod endpoints;
pub mod types;
pub mod util_types;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
#[repr(transparent)]
pub struct Required<T>(pub T);

impl<T: TS + 'static> TS for Required<T> {
    const EXPORT_TO: Option<&'static str> = None;

    fn decl() -> String {
        unimplemented!()
    }

    fn name() -> String {
        T::name()
    }

    fn inline() -> String {
        T::name()
    }

    fn inline_flattened() -> String {
        unimplemented!()
    }

    fn dependencies() -> Vec<ts_rs::Dependency> {
        ts_rs::Dependency::from_ty::<T>().into_iter().collect()
    }

    fn transparent() -> bool {
        false
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
#[repr(transparent)]
pub struct Optional<T>(pub Option<T>);

impl<T: TS + 'static> TS for Optional<T> {
    const EXPORT_TO: Option<&'static str> = None;

    fn decl() -> String {
        unimplemented!()
    }

    fn name() -> String {
        T::name()
    }

    fn inline() -> String {
        format!("Partial<{}>", T::name())
    }

    fn inline_flattened() -> String {
        unimplemented!()
    }

    fn dependencies() -> Vec<ts_rs::Dependency> {
        ts_rs::Dependency::from_ty::<T>().into_iter().collect()
    }

    fn transparent() -> bool {
        false
    }
}

impl<T: TS> Deref for Optional<T> {
    type Target = Option<T>;

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

impl<T: TS> DerefMut for Optional<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

pub trait Packed: 'static {
    type Input: 'static;

    fn pack_from(val: Self::Input) -> Self;
}
