use falcorn_core::{ProtocolType as CoreProtocolType, WorkerClass as CoreWorkerClass};
use pyo3::exceptions::PyValueError;
use pyo3::prelude::*;

// ####
// ##       WORKER CLASS ENUM FOR PYTHON
// #####
#[pyclass(eq, eq_int)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum WorkerClass {
    /// Synchronous blocking workers
    Sync,
    /// Asynchronous non-blocking workers
    Async,
}

impl WorkerClass {
    /// Convert to core WorkerClass
    pub(crate) fn to_core(&self) -> CoreWorkerClass {
        match self {
            Self::Sync => CoreWorkerClass::Sync,
            Self::Async => CoreWorkerClass::Async,
        }
    }
}

#[pymethods]
impl WorkerClass {
    #[new]
    pub fn new(class: &str) -> PyResult<Self> {
        match class.to_lowercase().as_str() {
            "sync" => Ok(Self::Sync),
            "async" => Ok(Self::Async),
            _ => Err(PyValueError::new_err(
                "WorkerClass must be 'sync' or 'async'",
            )),
        }
    }

    pub fn __str__(&self) -> &'static str {
        match self {
            Self::Sync => "sync",
            Self::Async => "async",
        }
    }

    fn __repr__(&self) -> String {
        format!("WorkerClass.{}", self.__str__().to_uppercase())
    }
}

// ####
// ##       PROTOCOL TYPE FOR PYTHON
// #####
#[pyclass(eq, eq_int)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProtocolType {
    /// Synchronous blocking workers
    Wsgi,
    /// Asynchronous non-blocking workers
    Asgi,
}

impl ProtocolType {
    /// Convert to core ProtocolType
    pub(crate) fn to_core(&self) -> CoreProtocolType {
        match self {
            Self::Wsgi => CoreProtocolType::Wsgi,
            Self::Asgi => CoreProtocolType::Asgi,
        }
    }
}

#[pymethods]
impl ProtocolType {
    #[new]
    pub fn new(class: &str) -> PyResult<Self> {
        match class.to_lowercase().as_str() {
            "wsgi" => Ok(Self::Wsgi),
            "asgi" => Ok(Self::Asgi),
            _ => Err(PyValueError::new_err(
                "ProtocolType must be 'wsgi' or 'asgi'",
            )),
        }
    }

    pub fn __str__(&self) -> &'static str {
        match self {
            Self::Wsgi => "wsgi",
            Self::Asgi => "asgi",
        }
    }

    fn __repr__(&self) -> String {
        format!("ProtocolType.{}", self.__str__().to_uppercase())
    }
}
