package db

import (
	"time"
)

// Option is a database configuration option.
// It is exported for users to store and pass around Options,
// but the unexported function signature prevents users from writing
// arbitrary Options.
type Option func(*dbImpl)

// Host sets the remote hostname for the database to connect to.
// NOTE that no special logic occurs for setting default values or
// validating that this value is set, so it is up to the client to ensure
// this value is set appropriately.
func Host(h string) Option {
	return func(db *dbImpl) {
		db.state.config.host = h
	}
}

// Port sets the remote port for the database to connect to.
// NOTE that no special logic occurs for setting default values or
// validating that this value is set, so it is up to the client to ensure
// this value is set appropriately.
func Port(p int) Option {
	return func(db *dbImpl) {
		db.state.config.port = p
	}
}

// User sets the username for the database to use on connect.
// NOTE that no special logic occurs for setting default values or
// validating that this value is set, so it is up to the client to ensure
// this value is set appropriately.
func User(u string) Option {
	return func(db *dbImpl) {
		db.state.config.user = u
	}
}

// Password sets the password to set on connect.
// NOTE that no special logic occurs for setting default values or
// validating that this value is set, so it is up to the client to ensure
// this value is set appropriately.
func Password(pw string) Option {
	return func(db *dbImpl) {
		db.state.config.password = pw
	}
}

// DBName sets the name of the database to operate on.
// NOTE that no special logic occurs for setting default values or
// validating that this value is set, so it is up to the client to ensure
// this value is set appropriately.
func DBName(n string) Option {
	return func(db *dbImpl) {
		db.state.config.dbName = n
	}
}

// MaxOpenConns sets the maximum number of active in-flight database connections.
// NOTE that no special logic occurs for setting default values or
// validating that this value is set, so it is up to the client to ensure
// this value is set appropriately.
func MaxOpenConns(c int) Option {
	return func(db *dbImpl) {
		db.state.config.maxOpenConns = c
	}
}

// MaxQueueSize sets the maximum queueing size for callers waiting
// to perform a db operation.  If the queue is full, an error is returned immediately.
// NOTE that no special logic occurs for setting default values or
// validating that this value is set, so it is up to the client to ensure
// this value is set appropriately.
func MaxQueueSize(s int) Option {
	return func(db *dbImpl) {
		db.state.config.maxQueueSize = s
	}
}

// MaxIdleConns sets the maximum number of open (not necessarily active, in-flight) database connections.
// NOTE that no special logic occurs for setting default values or
// validating that this value is set, so it is up to the client to ensure
// this value is set appropriately.
func MaxIdleConns(c int) Option {
	return func(db *dbImpl) {
		db.state.config.maxIdleConns = c
	}
}

// ConnAcquireTimeout sets the timeout threshold for acquiring a
// database connection.
// NOTE that no special logic occurs for setting default values or
// validating that this value is set, so it is up to the client to ensure
// this value is set appropriately.
func ConnAcquireTimeout(t time.Duration) Option {
	return func(db *dbImpl) {
		db.state.config.connAcquireTimeout = t
	}
}

// RequestTimeout sets the timeout threshold for a database operation.
// NOTE that no special logic occurs for setting default values or
// validating that this value is set, so it is up to the client to ensure
// this value is set appropriately.
func RequestTimeout(t time.Duration) Option {
	return func(db *dbImpl) {
		db.state.config.requestTimeout = t
	}
}

// MaxConnAge sets the maximum age for a connection to live before being recycled.
// NOTE that no special logic occurs for setting default values or
// validating that this value is set, so it is up to the client to ensure
// this value is set appropriately.
func MaxConnAge(t time.Duration) Option {
	return func(db *dbImpl) {
		db.state.config.maxConnAge = t
	}
}

// DriverName sets the name of the sql driver to use for database operations.
// NOTE that no special logic occurs for setting default values or
// validating that this value is set, so it is up to the client to ensure
// this value is set appropriately.
func DriverName(n string) Option {
	return func(db *dbImpl) {
		db.state.config.driverName = n
	}
}

// EventCallbacks sets the callback handlers for database and management events.
// Either callback may be set to nil.
func EventCallbacks(dbCb DBCallback, runCb RunCallback) Option {
	return func(db *dbImpl) {
		db.evManager.setCbs(dbCb, runCb)
	}
}

// DBCallback defines the format of the callbacks which clients can use
// to be notified of events related to database operations, such as
// queries, row scans, etc.
type DBCallback func(evName, queryName string, d time.Duration)

// RunCallback defines the format of the callbacks which clients can use
// to be notified of events related to asynchronous database management, such as
// recycle errors.
type RunCallback func(evName string)
