package vfs

import (
	
	
	
	
	
	

	
	

	
	
	
)

// ExportHostFunctions is an internal API users need not call directly.
//
// ExportHostFunctions registers the required VFS host functions
// with the provided env module.
func ( wazero.HostModuleBuilder) wazero.HostModuleBuilder {
	util.ExportFuncII(, "go_vfs_find", vfsFind)
	util.ExportFuncIIJ(, "go_localtime", vfsLocaltime)
	util.ExportFuncIIII(, "go_randomness", vfsRandomness)
	util.ExportFuncIII(, "go_sleep", vfsSleep)
	util.ExportFuncIII(, "go_current_time_64", vfsCurrentTime64)
	util.ExportFuncIIIII(, "go_full_pathname", vfsFullPathname)
	util.ExportFuncIIII(, "go_delete", vfsDelete)
	util.ExportFuncIIIII(, "go_access", vfsAccess)
	util.ExportFuncIIIIIII(, "go_open", vfsOpen)
	util.ExportFuncII(, "go_close", vfsClose)
	util.ExportFuncIIIIJ(, "go_read", vfsRead)
	util.ExportFuncIIIIJ(, "go_write", vfsWrite)
	util.ExportFuncIIJ(, "go_truncate", vfsTruncate)
	util.ExportFuncIII(, "go_sync", vfsSync)
	util.ExportFuncIII(, "go_file_size", vfsFileSize)
	util.ExportFuncIIII(, "go_file_control", vfsFileControl)
	util.ExportFuncII(, "go_sector_size", vfsSectorSize)
	util.ExportFuncII(, "go_device_characteristics", vfsDeviceCharacteristics)
	util.ExportFuncIII(, "go_lock", vfsLock)
	util.ExportFuncIII(, "go_unlock", vfsUnlock)
	util.ExportFuncIII(, "go_check_reserved_lock", vfsCheckReservedLock)
	util.ExportFuncIIIIII(, "go_shm_map", vfsShmMap)
	util.ExportFuncIIIII(, "go_shm_lock", vfsShmLock)
	util.ExportFuncIII(, "go_shm_unmap", vfsShmUnmap)
	util.ExportFuncVI(, "go_shm_barrier", vfsShmBarrier)
	return 
}

func vfsFind( context.Context,  api.Module,  ptr_t) uint32 {
	 := util.ReadString(, , _MAX_NAME)
	if  := Find();  != nil &&  != (vfsOS{}) {
		return 1
	}
	return 0
}

func vfsLocaltime( context.Context,  api.Module,  ptr_t,  int64) _ErrorCode {
	const  = 32 / 8
	 := time.Unix(, 0)
	// https://pubs.opengroup.org/onlinepubs/7908799/xsh/time.h.html
	util.Write32(, +0*, int32(.Second()))
	util.Write32(, +1*, int32(.Minute()))
	util.Write32(, +2*, int32(.Hour()))
	util.Write32(, +3*, int32(.Day()))
	util.Write32(, +4*, int32(.Month()-time.January))
	util.Write32(, +5*, int32(.Year()-1900))
	util.Write32(, +6*, int32(.Weekday()-time.Sunday))
	util.Write32(, +7*, int32(.YearDay()-1))
	util.WriteBool(, +8*, .IsDST())
	return _OK
}

func vfsRandomness( context.Context,  api.Module,  ptr_t,  int32,  ptr_t) uint32 {
	 := util.View(, , int64())
	,  := rand.Reader.Read()
	return uint32()
}

func vfsSleep( context.Context,  api.Module,  ptr_t,  int32) _ErrorCode {
	time.Sleep(time.Duration() * time.Microsecond)
	return _OK
}

func vfsCurrentTime64( context.Context,  api.Module, ,  ptr_t) _ErrorCode {
	,  := julianday.Date(time.Now())
	 := *86_400_000 + /1_000_000
	util.Write64(, , )
	return _OK
}

func vfsFullPathname( context.Context,  api.Module, ,  ptr_t,  int32,  ptr_t) _ErrorCode {
	 := vfsGet(, )
	 := util.ReadString(, , _MAX_PATHNAME)

	,  := .FullPathname()

	if len() >= int() {
		return _CANTOPEN_FULLPATH
	}
	util.WriteString(, , )

	return vfsErrorCode(, , _CANTOPEN_FULLPATH)
}

func vfsDelete( context.Context,  api.Module, ,  ptr_t,  int32) _ErrorCode {
	 := vfsGet(, )
	 := util.ReadString(, , _MAX_PATHNAME)

	 := .Delete(,  != 0)
	return vfsErrorCode(, , _IOERR_DELETE)
}

func vfsAccess( context.Context,  api.Module, ,  ptr_t,  AccessFlag,  ptr_t) _ErrorCode {
	 := vfsGet(, )
	 := util.ReadString(, , _MAX_PATHNAME)

	,  := .Access(, )
	util.WriteBool(, , )
	return vfsErrorCode(, , _IOERR_ACCESS)
}

func vfsOpen( context.Context,  api.Module, , ,  ptr_t,  OpenFlag, ,  ptr_t) _ErrorCode {
	 := vfsGet(, )
	 := GetFilename(, , , )

	var  File
	var  error
	if ,  := .(VFSFilename);  {
		, ,  = .OpenFilename(, )
	} else {
		, ,  = .Open(.String(), )
	}
	if  != nil {
		return vfsErrorCode(, , _CANTOPEN)
	}

	if ,  := .(FilePowersafeOverwrite);  {
		if ,  := sql3util.ParseBool(.URIParameter("psow"));  {
			.SetPowersafeOverwrite()
		}
	}
	if ,  := .(FileSharedMemory);  &&  != 0 {
		util.WriteBool(, , .SharedMemory() != nil)
	}
	if  != 0 {
		util.Write32(, , )
	}
	 = cksmWrapFile(, )
	vfsFileRegister(, , , )
	return _OK
}

func vfsClose( context.Context,  api.Module,  ptr_t) _ErrorCode {
	 := vfsFileClose(, , )
	return vfsErrorCode(, , _IOERR_CLOSE)
}

func vfsRead( context.Context,  api.Module, ,  ptr_t,  int32,  int64) _ErrorCode {
	 := vfsFileGet(, , ).(File)
	 := util.View(, , int64())

	,  := .ReadAt(, )
	if  == int() {
		return _OK
	}
	if  != io.EOF {
		return vfsErrorCode(, , _IOERR_READ)
	}
	clear([:])
	return _IOERR_SHORT_READ
}

func vfsWrite( context.Context,  api.Module, ,  ptr_t,  int32,  int64) _ErrorCode {
	 := vfsFileGet(, , ).(File)
	 := util.View(, , int64())

	,  := .WriteAt(, )
	return vfsErrorCode(, , _IOERR_WRITE)
}

func vfsTruncate( context.Context,  api.Module,  ptr_t,  int64) _ErrorCode {
	 := vfsFileGet(, , ).(File)
	 := .Truncate()
	return vfsErrorCode(, , _IOERR_TRUNCATE)
}

func vfsSync( context.Context,  api.Module,  ptr_t,  SyncFlag) _ErrorCode {
	 := vfsFileGet(, , ).(File)
	 := .Sync()
	return vfsErrorCode(, , _IOERR_FSYNC)
}

func vfsFileSize( context.Context,  api.Module, ,  ptr_t) _ErrorCode {
	 := vfsFileGet(, , ).(File)
	,  := .Size()
	util.Write64(, , )
	return vfsErrorCode(, , _IOERR_SEEK)
}

func vfsLock( context.Context,  api.Module,  ptr_t,  LockLevel) _ErrorCode {
	 := vfsFileGet(, , ).(File)
	 := .Lock()
	return vfsErrorCode(, , _IOERR_LOCK)
}

func vfsUnlock( context.Context,  api.Module,  ptr_t,  LockLevel) _ErrorCode {
	 := vfsFileGet(, , ).(File)
	 := .Unlock()
	return vfsErrorCode(, , _IOERR_UNLOCK)
}

func vfsCheckReservedLock( context.Context,  api.Module, ,  ptr_t) _ErrorCode {
	 := vfsFileGet(, , ).(File)
	,  := .CheckReservedLock()
	util.WriteBool(, , )
	return vfsErrorCode(, , _IOERR_CHECKRESERVEDLOCK)
}

func vfsFileControl( context.Context,  api.Module,  ptr_t,  _FcntlOpcode,  ptr_t) _ErrorCode {
	 := vfsFileGet(, , ).(File)
	if ,  := .(fileControl);  {
		return .fileControl(, , , )
	}
	return vfsFileControlImpl(, , , , )
}

func vfsFileControlImpl( context.Context,  api.Module,  File,  _FcntlOpcode,  ptr_t) _ErrorCode {
	switch  {
	case _FCNTL_LOCKSTATE:
		if ,  := .(FileLockState);  {
			if  := .LockState();  <= LOCK_EXCLUSIVE {
				util.Write32(, , )
				return _OK
			}
		}

	case _FCNTL_PERSIST_WAL:
		if ,  := .(FilePersistWAL);  {
			if  := util.Read32[int32](, );  < 0 {
				util.WriteBool(, , .PersistWAL())
			} else {
				.SetPersistWAL( != 0)
			}
			return _OK
		}

	case _FCNTL_POWERSAFE_OVERWRITE:
		if ,  := .(FilePowersafeOverwrite);  {
			if  := util.Read32[int32](, );  < 0 {
				util.WriteBool(, , .PowersafeOverwrite())
			} else {
				.SetPowersafeOverwrite( != 0)
			}
			return _OK
		}

	case _FCNTL_CHUNK_SIZE:
		if ,  := .(FileChunkSize);  {
			 := util.Read32[int32](, )
			.ChunkSize(int())
			return _OK
		}

	case _FCNTL_SIZE_HINT:
		if ,  := .(FileSizeHint);  {
			 := util.Read64[int64](, )
			 := .SizeHint()
			return vfsErrorCode(, , _IOERR_TRUNCATE)
		}

	case _FCNTL_HAS_MOVED:
		if ,  := .(FileHasMoved);  {
			,  := .HasMoved()
			util.WriteBool(, , )
			return vfsErrorCode(, , _IOERR_FSTAT)
		}

	case _FCNTL_OVERWRITE:
		if ,  := .(FileOverwrite);  {
			 := .Overwrite()
			return vfsErrorCode(, , _IOERR)
		}

	case _FCNTL_SYNC:
		if ,  := .(FileSync);  {
			var  string
			if  != 0 {
				 = util.ReadString(, , _MAX_PATHNAME)
			}
			 := .SyncSuper()
			return vfsErrorCode(, , _IOERR)
		}

	case _FCNTL_COMMIT_PHASETWO:
		if ,  := .(FileCommitPhaseTwo);  {
			 := .CommitPhaseTwo()
			return vfsErrorCode(, , _IOERR)
		}

	case _FCNTL_BEGIN_ATOMIC_WRITE:
		if ,  := .(FileBatchAtomicWrite);  {
			 := .BeginAtomicWrite()
			return vfsErrorCode(, , _IOERR_BEGIN_ATOMIC)
		}
	case _FCNTL_COMMIT_ATOMIC_WRITE:
		if ,  := .(FileBatchAtomicWrite);  {
			 := .CommitAtomicWrite()
			return vfsErrorCode(, , _IOERR_COMMIT_ATOMIC)
		}
	case _FCNTL_ROLLBACK_ATOMIC_WRITE:
		if ,  := .(FileBatchAtomicWrite);  {
			 := .RollbackAtomicWrite()
			return vfsErrorCode(, , _IOERR_ROLLBACK_ATOMIC)
		}

	case _FCNTL_CKPT_START:
		if ,  := .(FileCheckpoint);  {
			.CheckpointStart()
			return _OK
		}
	case _FCNTL_CKPT_DONE:
		if ,  := .(FileCheckpoint);  {
			.CheckpointDone()
			return _OK
		}

	case _FCNTL_PRAGMA:
		if ,  := .(FilePragma);  {
			var  string
			 := util.Read32[ptr_t](, +1*ptrlen)
			 := util.ReadString(, , _MAX_SQL_LENGTH)
			if  := util.Read32[ptr_t](, +2*ptrlen);  != 0 {
				 = util.ReadString(, , _MAX_SQL_LENGTH)
			}

			,  := .Pragma(strings.ToLower(), )

			 := vfsErrorCode(, , _ERROR)
			if  == _ERROR {
				 = .Error()
			}
			if  != "" {
				 := .ExportedFunction("sqlite3_malloc64")
				 := [...]stk_t{stk_t(len() + 1)}
				if  := .CallWithStack(, [:]);  != nil {
					panic()
				}
				util.Write32(, , ptr_t([0]))
				util.WriteString(, ptr_t([0]), )
			}
			return 
		}

	case _FCNTL_BUSYHANDLER:
		if ,  := .(FileBusyHandler);  {
			 := util.Read64[stk_t](, )
			 := .ExportedFunction("sqlite3_invoke_busy_handler_go")
			.BusyHandler(func() bool {
				 := [...]stk_t{}
				if  := .CallWithStack(, [:]);  != nil {
					panic()
				}
				return uint32([0]) != 0
			})
			return _OK
		}

	case _FCNTL_LOCK_TIMEOUT:
		if ,  := .(FileSharedMemory);  {
			if ,  := .SharedMemory().(blockingSharedMemory);  {
				.shmEnableBlocking(util.ReadBool(, ))
				return _OK
			}
		}

	case _FCNTL_PDB:
		if ,  := .(filePDB);  {
			.SetDB(.Value(util.ConnKey{}))
			return _OK
		}

	case _FCNTL_NULL_IO:
		.Close()
		return _OK
	}

	return _NOTFOUND
}

func vfsSectorSize( context.Context,  api.Module,  ptr_t) uint32 {
	 := vfsFileGet(, , ).(File)
	return uint32(.SectorSize())
}

func vfsDeviceCharacteristics( context.Context,  api.Module,  ptr_t) DeviceCharacteristic {
	 := vfsFileGet(, , ).(File)
	return .DeviceCharacteristics()
}

func vfsShmBarrier( context.Context,  api.Module,  ptr_t) {
	 := vfsFileGet(, , ).(FileSharedMemory).SharedMemory()
	.shmBarrier()
}

func vfsShmMap( context.Context,  api.Module,  ptr_t, , ,  int32,  ptr_t) _ErrorCode {
	 := vfsFileGet(, , ).(FileSharedMemory).SharedMemory()
	,  := .shmMap(, , , ,  != 0)
	util.Write32(, , )
	return vfsErrorCode(, , _IOERR_SHMMAP)
}

func vfsShmLock( context.Context,  api.Module,  ptr_t, ,  int32,  _ShmFlag) _ErrorCode {
	 := vfsFileGet(, , ).(FileSharedMemory).SharedMemory()
	 := .shmLock(, , )
	return vfsErrorCode(, , _IOERR_SHMLOCK)
}

func vfsShmUnmap( context.Context,  api.Module,  ptr_t,  int32) _ErrorCode {
	 := vfsFileGet(, , ).(FileSharedMemory).SharedMemory()
	.shmUnmap( != 0)
	return _OK
}

func vfsGet( api.Module,  ptr_t) VFS {
	var  string
	if  != 0 {
		const  = 16
		 := util.Read32[ptr_t](, +)
		 = util.ReadString(, , _MAX_NAME)
	}
	if  := Find();  != nil {
		return 
	}
	panic(util.NoVFSErr + util.ErrorString())
}

func vfsFileRegister( context.Context,  api.Module,  ptr_t,  File) {
	const  = 4
	 := util.AddHandle(, )
	util.Write32(, +, )
}

func vfsFileGet( context.Context,  api.Module,  ptr_t) any {
	const  = 4
	 := util.Read32[ptr_t](, +)
	return util.GetHandle(, )
}

func vfsFileClose( context.Context,  api.Module,  ptr_t) error {
	const  = 4
	 := util.Read32[ptr_t](, +)
	return util.DelHandle(, )
}

func vfsErrorCode( context.Context,  error,  _ErrorCode) _ErrorCode {
	var  error

	switch err := .(type) {
	case nil:
		 = _OK
	case _ErrorCode:
		 = 
	case sysError:
		 = .code
		 = .error
	default:
		switch  := reflect.ValueOf(); .Kind() {
		case reflect.Uint8, reflect.Uint16:
			 = _ErrorCode(.Uint())
		default:
			 = 
		}
	}

	util.SetSystemError(, )
	return 
}

// SystemError tags an error with a given
// sqlite3.ErrorCode or sqlite3.ExtendedErrorCode.
func [ interface{ ~uint8 | ~uint16 }]( error,  ) error {
	if  == nil {
		return nil
	}
	return sysError{error: , code: _ErrorCode()}
}

type sysError struct {
	error
	code _ErrorCode
}