use super::ffi;
use super::unlock_notify;
use super::StatementStatus;
#[cfg(feature = "modern_sqlite")]
use crate::util::SqliteMallocString;
use std::ffi::CStr;
use std::os::raw::c_int;
use std::ptr;
use std::sync::Arc;

// Private newtype for raw sqlite3_stmts that finalize themselves when dropped.
#[derive(Debug)]
pub struct RawStatement {
    ptr: *mut ffi::sqlite3_stmt,
    tail: usize,
    // Cached indices of named parameters, computed on the fly.
    cache: crate::util::ParamIndexCache,
    // Cached SQL (trimmed) that we use as the key when we're in the statement
    // cache. This is None for statements which didn't come from the statement
    // cache.
    //
    // This is probably the same as `self.sql()` in most cases, but we don't
    // care either way -- It's a better cache key as it is anyway since it's the
    // actual source we got from rust.
    //
    // One example of a case where the result of `sqlite_sql` and the value in
    // `statement_cache_key` might differ is if the statement has a `tail`.
    statement_cache_key: Option<Arc<str>>,
}

impl RawStatement {
    #[inline]
    pub unsafe fn new(stmt: *mut ffi::sqlite3_stmt, tail: usize) -> RawStatement {
        RawStatement {
            ptr: stmt,
            tail,
            cache: Default::default(),
            statement_cache_key: None,
        }
    }

    #[inline]
    pub fn is_null(&self) -> bool {
        self.ptr.is_null()
    }

    #[inline]
    pub(crate) fn set_statement_cache_key(&mut self, p: impl Into<Arc<str>>) {
        self.statement_cache_key = Some(p.into());
    }

    #[inline]
    pub(crate) fn statement_cache_key(&self) -> Option<Arc<str>> {
        self.statement_cache_key.clone()
    }

    #[inline]
    pub unsafe fn ptr(&self) -> *mut ffi::sqlite3_stmt {
        self.ptr
    }

    #[inline]
    pub fn column_count(&self) -> usize {
        // Note: Can't cache this as it changes if the schema is altered.
        unsafe { ffi::sqlite3_column_count(self.ptr) as usize }
    }

    #[inline]
    pub fn column_type(&self, idx: usize) -> c_int {
        unsafe { ffi::sqlite3_column_type(self.ptr, idx as c_int) }
    }

    #[inline]
    #[cfg(feature = "column_decltype")]
    pub fn column_decltype(&self, idx: usize) -> Option<&CStr> {
        unsafe {
            let decltype = ffi::sqlite3_column_decltype(self.ptr, idx as c_int);
            if decltype.is_null() {
                None
            } else {
                Some(CStr::from_ptr(decltype))
            }
        }
    }

    #[inline]
    pub fn column_name(&self, idx: usize) -> Option<&CStr> {
        let idx = idx as c_int;
        if idx < 0 || idx >= self.column_count() as c_int {
            return None;
        }
        unsafe {
            let ptr = ffi::sqlite3_column_name(self.ptr, idx);
            // If ptr is null here, it's an OOM, so there's probably nothing
            // meaningful we can do. Just assert instead of returning None.
            assert!(
                !ptr.is_null(),
                "Null pointer from sqlite3_column_name: Out of memory?"
            );
            Some(CStr::from_ptr(ptr))
        }
    }

    #[cfg_attr(not(feature = "unlock_notify"), inline)]
    pub fn step(&self) -> c_int {
        if cfg!(feature = "unlock_notify") {
            let db = unsafe { ffi::sqlite3_db_handle(self.ptr) };
            let mut rc;
            loop {
                rc = unsafe { ffi::sqlite3_step(self.ptr) };
                if unsafe { !unlock_notify::is_locked(db, rc) } {
                    break;
                }
                rc = unsafe { unlock_notify::wait_for_unlock_notify(db) };
                if rc != ffi::SQLITE_OK {
                    break;
                }
                self.reset();
            }
            rc
        } else {
            unsafe { ffi::sqlite3_step(self.ptr) }
        }
    }

    #[inline]
    pub fn reset(&self) -> c_int {
        unsafe { ffi::sqlite3_reset(self.ptr) }
    }

    #[inline]
    pub fn bind_parameter_count(&self) -> usize {
        unsafe { ffi::sqlite3_bind_parameter_count(self.ptr) as usize }
    }

    #[inline]
    pub fn bind_parameter_index(&self, name: &str) -> Option<usize> {
        self.cache.get_or_insert_with(name, |param_cstr| {
            let r = unsafe { ffi::sqlite3_bind_parameter_index(self.ptr, param_cstr.as_ptr()) };
            match r {
                0 => None,
                i => Some(i as usize),
            }
        })
    }

    #[inline]
    pub fn bind_parameter_name(&self, index: i32) -> Option<&CStr> {
        unsafe {
            let name = ffi::sqlite3_bind_parameter_name(self.ptr, index);
            if name.is_null() {
                None
            } else {
                Some(CStr::from_ptr(name))
            }
        }
    }

    #[inline]
    pub fn clear_bindings(&self) -> c_int {
        unsafe { ffi::sqlite3_clear_bindings(self.ptr) }
    }

    #[inline]
    pub fn sql(&self) -> Option<&CStr> {
        if self.ptr.is_null() {
            None
        } else {
            Some(unsafe { CStr::from_ptr(ffi::sqlite3_sql(self.ptr)) })
        }
    }

    #[inline]
    pub fn finalize(mut self) -> c_int {
        self.finalize_()
    }

    #[inline]
    fn finalize_(&mut self) -> c_int {
        let r = unsafe { ffi::sqlite3_finalize(self.ptr) };
        self.ptr = ptr::null_mut();
        r
    }

    // does not work for PRAGMA
    #[inline]
    #[cfg(all(feature = "extra_check", feature = "modern_sqlite"))] // 3.7.4
    pub fn readonly(&self) -> bool {
        unsafe { ffi::sqlite3_stmt_readonly(self.ptr) != 0 }
    }

    #[inline]
    #[cfg(feature = "modern_sqlite")] // 3.14.0
    pub(crate) fn expanded_sql(&self) -> Option<SqliteMallocString> {
        unsafe { SqliteMallocString::from_raw(ffi::sqlite3_expanded_sql(self.ptr)) }
    }

    #[inline]
    pub fn get_status(&self, status: StatementStatus, reset: bool) -> i32 {
        assert!(!self.ptr.is_null());
        unsafe { ffi::sqlite3_stmt_status(self.ptr, status as i32, reset as i32) }
    }

    #[inline]
    #[cfg(feature = "extra_check")]
    pub fn has_tail(&self) -> bool {
        self.tail != 0
    }

    #[inline]
    pub fn tail(&self) -> usize {
        self.tail
    }
}

impl Drop for RawStatement {
    fn drop(&mut self) {
        self.finalize_();
    }
}
