package sqlite3

import (
	
	
	

	
)

// Context is the context in which an SQL function executes.
// An SQLite [Context] is in no way related to a Go [context.Context].
//
// https://sqlite.org/c3ref/context.html
type Context struct {
	c      *Conn
	handle ptr_t
}

// Conn returns the database connection of the
// [Conn.CreateFunction] or [Conn.CreateWindowFunction]
// routines that originally registered the application defined function.
//
// https://sqlite.org/c3ref/context_db_handle.html
func ( Context) () *Conn {
	return .c
}

// SetAuxData saves metadata for argument n of the function.
//
// https://sqlite.org/c3ref/get_auxdata.html
func ( Context) ( int,  any) {
	 := util.AddHandle(.c.ctx, )
	.c.call("sqlite3_set_auxdata_go", stk_t(.handle), stk_t(), stk_t())
}

// GetAuxData returns metadata for argument n of the function.
//
// https://sqlite.org/c3ref/get_auxdata.html
func ( Context) ( int) any {
	 := ptr_t(.c.call("sqlite3_get_auxdata", stk_t(.handle), stk_t()))
	return util.GetHandle(.c.ctx, )
}

// ResultBool sets the result of the function to a bool.
// SQLite does not have a separate boolean storage class.
// Instead, boolean values are stored as integers 0 (false) and 1 (true).
//
// https://sqlite.org/c3ref/result_blob.html
func ( Context) ( bool) {
	var  int64
	if  {
		 = 1
	}
	.ResultInt64()
}

// ResultInt sets the result of the function to an int.
//
// https://sqlite.org/c3ref/result_blob.html
func ( Context) ( int) {
	.ResultInt64(int64())
}

// ResultInt64 sets the result of the function to an int64.
//
// https://sqlite.org/c3ref/result_blob.html
func ( Context) ( int64) {
	.c.call("sqlite3_result_int64",
		stk_t(.handle), stk_t())
}

// ResultFloat sets the result of the function to a float64.
//
// https://sqlite.org/c3ref/result_blob.html
func ( Context) ( float64) {
	.c.call("sqlite3_result_double",
		stk_t(.handle), stk_t(math.Float64bits()))
}

// ResultText sets the result of the function to a string.
//
// https://sqlite.org/c3ref/result_blob.html
func ( Context) ( string) {
	 := .c.newString()
	.c.call("sqlite3_result_text_go",
		stk_t(.handle), stk_t(), stk_t(len()))
}

// ResultRawText sets the text result of the function to a []byte.
//
// https://sqlite.org/c3ref/result_blob.html
func ( Context) ( []byte) {
	if len() == 0 {
		.ResultText("")
		return
	}
	 := .c.newBytes()
	.c.call("sqlite3_result_text_go",
		stk_t(.handle), stk_t(), stk_t(len()))
}

// ResultBlob sets the result of the function to a []byte.
//
// https://sqlite.org/c3ref/result_blob.html
func ( Context) ( []byte) {
	if len() == 0 {
		.ResultZeroBlob(0)
		return
	}
	 := .c.newBytes()
	.c.call("sqlite3_result_blob_go",
		stk_t(.handle), stk_t(), stk_t(len()))
}

// ResultZeroBlob sets the result of the function to a zero-filled, length n BLOB.
//
// https://sqlite.org/c3ref/result_blob.html
func ( Context) ( int64) {
	.c.call("sqlite3_result_zeroblob64",
		stk_t(.handle), stk_t())
}

// ResultNull sets the result of the function to NULL.
//
// https://sqlite.org/c3ref/result_blob.html
func ( Context) () {
	.c.call("sqlite3_result_null",
		stk_t(.handle))
}

// ResultTime sets the result of the function to a [time.Time].
//
// https://sqlite.org/c3ref/result_blob.html
func ( Context) ( time.Time,  TimeFormat) {
	switch  {
	case TimeFormatDefault, TimeFormatAuto, time.RFC3339Nano:
		.resultRFC3339Nano()
		return
	}
	switch v := .Encode().(type) {
	case string:
		.ResultText()
	case int64:
		.ResultInt64()
	case float64:
		.ResultFloat()
	default:
		panic(util.AssertErr())
	}
}

func ( Context) ( time.Time) {
	const  = int64(len(time.RFC3339Nano)) + 5

	 := .c.new()
	 := util.View(.c.mod, , )
	 = .AppendFormat([:0], time.RFC3339Nano)

	.c.call("sqlite3_result_text_go",
		stk_t(.handle), stk_t(), stk_t(len()))
}

// ResultPointer sets the result of the function to NULL, just like [Context.ResultNull],
// except that it also associates ptr with that NULL value such that it can be retrieved
// within an application-defined SQL function using [Value.Pointer].
//
// https://sqlite.org/c3ref/result_blob.html
func ( Context) ( any) {
	 := util.AddHandle(.c.ctx, )
	.c.call("sqlite3_result_pointer_go",
		stk_t(.handle), stk_t())
}

// ResultValue sets the result of the function to a copy of [Value].
//
// https://sqlite.org/c3ref/result_blob.html
func ( Context) ( Value) {
	if .c != .c {
		.ResultError(MISUSE)
		return
	}
	.c.call("sqlite3_result_value",
		stk_t(.handle), stk_t(.handle))
}

// ResultError sets the result of the function an error.
//
// https://sqlite.org/c3ref/result_blob.html
func ( Context) ( error) {
	if errors.Is(, NOMEM) {
		.c.call("sqlite3_result_error_nomem", stk_t(.handle))
		return
	}

	if errors.Is(, TOOBIG) {
		.c.call("sqlite3_result_error_toobig", stk_t(.handle))
		return
	}

	,  := errorCode(, _OK)
	if  != "" {
		defer .c.arena.mark()()
		 := .c.arena.string()
		.c.call("sqlite3_result_error",
			stk_t(.handle), stk_t(), stk_t(len()))
	}
	if  != _OK {
		.c.call("sqlite3_result_error_code",
			stk_t(.handle), stk_t())
	}
}

// ResultSubtype sets the subtype of the result of the function.
//
// https://sqlite.org/c3ref/result_subtype.html
func ( Context) ( uint) {
	.c.call("sqlite3_result_subtype",
		stk_t(.handle), stk_t(uint32()))
}

// VTabNoChange may return true if a column is being fetched as part
// of an update during which the column value will not change.
//
// https://sqlite.org/c3ref/vtab_nochange.html
func ( Context) () bool {
	 := int32(.c.call("sqlite3_vtab_nochange", stk_t(.handle)))
	return  != 0
}