use std::sync::{Arc, Mutex};
use crate::{
    Connection, CursorImpl, Error, ParameterCollectionRef, Preallocated, Prepared,
    connection::{ConnectionTransitions, FailedStateTransition},
    handles::{StatementConnection, StatementParent},
};
pub type SharedConnection<'env> = Arc<Mutex<Connection<'env>>>;
unsafe impl StatementParent for SharedConnection<'_> {}
impl<'env> ConnectionTransitions for SharedConnection<'env> {
    type StatementParent = Self;
    fn into_cursor(
        self,
        query: &str,
        params: impl ParameterCollectionRef,
        query_timeout_sec: Option<usize>,
    ) -> Result<Option<CursorImpl<StatementConnection<Self>>>, FailedStateTransition<Self>> {
        let guard = self
            .lock()
            .expect("Shared connection lock must not be poisned");
                        let result = guard.execute(query, params, query_timeout_sec);
        let result = result.map(|opt| opt.map(|cursor| cursor.into_stmt().into_sys()));
        drop(guard);
        if let Err(error) = result {
            return Err(FailedStateTransition {
                error,
                previous: self,
            });
        }
        let Some(stmt_ptr) = result.unwrap() else {
            return Ok(None);
        };
                let stmt = unsafe { StatementConnection::new(stmt_ptr, self) };
                let cursor = unsafe { CursorImpl::new(stmt) };
        Ok(Some(cursor))
    }
    fn into_prepared(self, query: &str) -> Result<Prepared<StatementConnection<Self>>, Error> {
        let guard = self
            .lock()
            .expect("Shared connection lock must not be poisoned");
        let stmt = guard.prepare(query)?;
        let stmt_ptr = stmt.into_handle().into_sys();
        drop(guard);
                let stmt = unsafe { StatementConnection::new(stmt_ptr, self) };
                let prepared = Prepared::new(stmt);
        Ok(prepared)
    }
    fn into_preallocated(self) -> Result<Preallocated<StatementConnection<Self>>, Error> {
        let guard = self
            .lock()
            .expect("Shared connection lock must not be poisoned");
        let stmt = guard.preallocate()?;
        let stmt_ptr = stmt.into_handle().into_sys();
        drop(guard);
                let stmt = unsafe { StatementConnection::new(stmt_ptr, self) };
                let preallocated = unsafe { Preallocated::new(stmt) };
        Ok(preallocated)
    }
}