use super::Blob;

use std::convert::TryFrom;
use std::mem::MaybeUninit;
use std::slice::from_raw_parts_mut;

use crate::ffi;
use crate::{Error, Result};

impl<'conn> Blob<'conn> {
    /// Write `buf` to `self` starting at `write_start`, returning an error if
    /// `write_start + buf.len()` is past the end of the blob.
    ///
    /// If an error is returned, no data is written.
    ///
    /// Note: the blob cannot be resized using this function -- that must be
    /// done using SQL (for example, an `UPDATE` statement).
    ///
    /// Note: This is part of the positional I/O API, and thus takes an absolute
    /// position write to, instead of using the internal position that can be
    /// manipulated by the `std::io` traits.
    ///
    /// Unlike the similarly named [`FileExt::write_at`][fext_write_at] function
    /// (from `std::os::unix`), it's always an error to perform a "short write".
    ///
    /// [fext_write_at]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#tymethod.write_at
    #[inline]
    pub fn write_at(&mut self, buf: &[u8], write_start: usize) -> Result<()> {
        let len = self.len();

        if buf.len().saturating_add(write_start) > len {
            return Err(Error::BlobSizeError);
        }
        // We know `len` fits in an `i32`, so either:
        //
        // 1. `buf.len() + write_start` overflows, in which case we'd hit the
        //    return above (courtesy of `saturating_add`).
        //
        // 2. `buf.len() + write_start` doesn't overflow but is larger than len,
        //    in which case ditto.
        //
        // 3. `buf.len() + write_start` doesn't overflow but is less than len.
        //    This means that both `buf.len()` and `write_start` can also be
        //    losslessly converted to i32, since `len` came from an i32.
        // Sanity check the above.
        debug_assert!(i32::try_from(write_start).is_ok() && i32::try_from(buf.len()).is_ok());
        unsafe {
            check!(ffi::sqlite3_blob_write(
                self.blob,
                buf.as_ptr() as *const _,
                buf.len() as i32,
                write_start as i32,
            ));
        }
        Ok(())
    }

    /// An alias for `write_at` provided for compatibility with the conceptually
    /// equivalent [`std::os::unix::FileExt::write_all_at`][write_all_at]
    /// function from libstd:
    ///
    /// [write_all_at]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileExt.html#method.write_all_at
    #[inline]
    pub fn write_all_at(&mut self, buf: &[u8], write_start: usize) -> Result<()> {
        self.write_at(buf, write_start)
    }

    /// Read as much as possible from `offset` to `offset + buf.len()` out of
    /// `self`, writing into `buf`. On success, returns the number of bytes
    /// written.
    ///
    /// If there's insufficient data in `self`, then the returned value will be
    /// less than `buf.len()`.
    ///
    /// See also [`Blob::raw_read_at`], which can take an uninitialized buffer,
    /// or [`Blob::read_at_exact`] which returns an error if the entire `buf` is
    /// not read.
    ///
    /// Note: This is part of the positional I/O API, and thus takes an absolute
    /// position to read from, instead of using the internal position that can
    /// be manipulated by the `std::io` traits. Consequently, it does not change
    /// that value either.
    #[inline]
    pub fn read_at(&self, buf: &mut [u8], read_start: usize) -> Result<usize> {
        // Safety: this is safe because `raw_read_at` never stores uninitialized
        // data into `as_uninit`.
        let as_uninit: &mut [MaybeUninit<u8>] =
            unsafe { from_raw_parts_mut(buf.as_mut_ptr() as *mut _, buf.len()) };
        self.raw_read_at(as_uninit, read_start).map(|s| s.len())
    }

    /// Read as much as possible from `offset` to `offset + buf.len()` out of
    /// `self`, writing into `buf`. On success, returns the portion of `buf`
    /// which was initialized by this call.
    ///
    /// If there's insufficient data in `self`, then the returned value will be
    /// shorter than `buf`.
    ///
    /// See also [`Blob::read_at`], which takes a `&mut [u8]` buffer instead of
    /// a slice of `MaybeUninit<u8>`.
    ///
    /// Note: This is part of the positional I/O API, and thus takes an absolute
    /// position to read from, instead of using the internal position that can
    /// be manipulated by the `std::io` traits. Consequently, it does not change
    /// that value either.
    #[inline]
    pub fn raw_read_at<'a>(
        &self,
        buf: &'a mut [MaybeUninit<u8>],
        read_start: usize,
    ) -> Result<&'a mut [u8]> {
        let len = self.len();

        let read_len = match len.checked_sub(read_start) {
            None | Some(0) => 0,
            Some(v) => v.min(buf.len()),
        };

        if read_len == 0 {
            // We could return `Ok(&mut [])`, but it seems confusing that the
            // pointers don't match, so fabricate a empty slice of u8 with the
            // same base pointer as `buf`.
            let empty = unsafe { from_raw_parts_mut(buf.as_mut_ptr() as *mut u8, 0) };
            return Ok(empty);
        }

        // At this point we believe `read_start as i32` is lossless because:
        //
        // 1. `len as i32` is known to be lossless, since it comes from a SQLite
        //    api returning an i32.
        //
        // 2. If we got here, `len.checked_sub(read_start)` was Some (or else
        //    we'd have hit the `if read_len == 0` early return), so `len` must
        //    be larger than `read_start`, and so it must fit in i32 as well.
        debug_assert!(i32::try_from(read_start).is_ok());

        // We also believe that `read_start + read_len <= len` because:
        //
        // 1. This is equivalent to `read_len <= len - read_start` via algebra.
        // 2. We know that `read_len` is `min(len - read_start, buf.len())`
        // 3. Expanding, this is `min(len - read_start, buf.len()) <= len - read_start`,
        //    or `min(A, B) <= A` which is clearly true.
        //
        // Note that this stuff is in debug_assert so no need to use checked_add
        // and such -- we'll always panic on overflow in debug builds.
        debug_assert!(read_start + read_len <= len);

        // These follow naturally.
        debug_assert!(buf.len() >= read_len);
        debug_assert!(i32::try_from(buf.len()).is_ok());
        debug_assert!(i32::try_from(read_len).is_ok());

        unsafe {
            check!(ffi::sqlite3_blob_read(
                self.blob,
                buf.as_mut_ptr() as *mut _,
                read_len as i32,
                read_start as i32,
            ));

            Ok(from_raw_parts_mut(buf.as_mut_ptr() as *mut u8, read_len))
        }
    }

    /// Equivalent to [`Blob::read_at`], but returns a `BlobSizeError` if `buf`
    /// is not fully initialized.
    #[inline]
    pub fn read_at_exact(&self, buf: &mut [u8], read_start: usize) -> Result<()> {
        let n = self.read_at(buf, read_start)?;
        if n != buf.len() {
            Err(Error::BlobSizeError)
        } else {
            Ok(())
        }
    }

    /// Equivalent to [`Blob::raw_read_at`], but returns a `BlobSizeError` if
    /// `buf` is not fully initialized.
    #[inline]
    pub fn raw_read_at_exact<'a>(
        &self,
        buf: &'a mut [MaybeUninit<u8>],
        read_start: usize,
    ) -> Result<&'a mut [u8]> {
        let buflen = buf.len();
        let initted = self.raw_read_at(buf, read_start)?;
        if initted.len() != buflen {
            Err(Error::BlobSizeError)
        } else {
            Ok(initted)
        }
    }
}

#[cfg(test)]
mod test {
    use crate::{Connection, DatabaseName, NO_PARAMS};
    // to ensure we don't modify seek pos
    use std::io::Seek as _;

    #[test]
    fn test_pos_io() {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE test_table(content BLOB);")
            .unwrap();
        db.execute(
            "INSERT INTO test_table(content) VALUES (ZEROBLOB(10))",
            NO_PARAMS,
        )
        .unwrap();

        let rowid = db.last_insert_rowid();
        let mut blob = db
            .blob_open(DatabaseName::Main, "test_table", "content", rowid, false)
            .unwrap();
        // modify the seek pos to ensure we aren't using it or modifying it.
        blob.seek(std::io::SeekFrom::Start(1)).unwrap();

        let one2ten: [u8; 10] = [1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        blob.write_at(&one2ten, 0).unwrap();

        let mut s = [0u8; 10];
        blob.read_at_exact(&mut s, 0).unwrap();
        assert_eq!(&s, &one2ten, "write should go through");
        assert!(blob.read_at_exact(&mut s, 1).is_err());

        blob.read_at_exact(&mut s, 0).unwrap();
        assert_eq!(&s, &one2ten, "should be unchanged");

        let mut fives = [0u8; 5];
        blob.read_at_exact(&mut fives, 0).unwrap();
        assert_eq!(&fives, &[1u8, 2, 3, 4, 5]);

        blob.read_at_exact(&mut fives, 5).unwrap();
        assert_eq!(&fives, &[6u8, 7, 8, 9, 10]);
        assert!(blob.read_at_exact(&mut fives, 7).is_err());
        assert!(blob.read_at_exact(&mut fives, 12).is_err());
        assert!(blob.read_at_exact(&mut fives, 10).is_err());
        assert!(blob.read_at_exact(&mut fives, i32::MAX as usize).is_err());
        assert!(blob
            .read_at_exact(&mut fives, i32::MAX as usize + 1)
            .is_err());

        // zero length writes are fine if in bounds
        blob.read_at_exact(&mut [], 10).unwrap();
        blob.read_at_exact(&mut [], 0).unwrap();
        blob.read_at_exact(&mut [], 5).unwrap();

        blob.write_all_at(&[16, 17, 18, 19, 20], 5).unwrap();
        blob.read_at_exact(&mut s, 0).unwrap();
        assert_eq!(&s, &[1u8, 2, 3, 4, 5, 16, 17, 18, 19, 20]);

        assert!(blob.write_at(&[100, 99, 98, 97, 96], 6).is_err());
        assert!(blob
            .write_at(&[100, 99, 98, 97, 96], i32::MAX as usize)
            .is_err());
        assert!(blob
            .write_at(&[100, 99, 98, 97, 96], i32::MAX as usize + 1)
            .is_err());

        blob.read_at_exact(&mut s, 0).unwrap();
        assert_eq!(&s, &[1u8, 2, 3, 4, 5, 16, 17, 18, 19, 20]);

        let mut s2: [std::mem::MaybeUninit<u8>; 10] = [std::mem::MaybeUninit::uninit(); 10];
        {
            let read = blob.raw_read_at_exact(&mut s2, 0).unwrap();
            assert_eq!(read, &s);
            assert!(std::ptr::eq(read.as_ptr(), s2.as_ptr().cast()));
        }

        let mut empty = [];
        assert!(std::ptr::eq(
            blob.raw_read_at_exact(&mut empty, 0).unwrap().as_ptr(),
            empty.as_ptr().cast(),
        ));
        assert!(blob.raw_read_at_exact(&mut s2, 5).is_err());

        let end_pos = blob.seek(std::io::SeekFrom::Current(0)).unwrap();
        assert_eq!(end_pos, 1);
    }
}
