// +build !go1.8

package xray

import (
	"context"
	"database/sql"
)

func (db *DB) Begin(ctx context.Context, opts interface{}) (*Tx, error) {
	tx, err := db.db.Begin()
	return &Tx{db, tx}, err
}

func (db *DB) Prepare(ctx context.Context, query string) (*Stmt, error) {
	stmt, err := db.db.Prepare(enhanceQuery(ctx, query))
	return &Stmt{db, stmt, query}, err
}

func (db *DB) Ping(ctx context.Context) error {
	return Capture(ctx, db.dbname, func(ctx context.Context) error {
		db.populate(ctx, "PING")
		return db.db.Ping()
	})
}

func (db *DB) Exec(ctx context.Context, query string, args ...interface{}) (sql.Result, error) {
	var res sql.Result

	err := Capture(ctx, db.dbname, func(ctx context.Context) error {
		db.populate(ctx, query)

		var err error
		res, err = db.db.Exec(enhanceQuery(ctx, query), args...)
		return err
	})

	return res, err
}

func (db *DB) Query(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) {
	var res *sql.Rows

	err := Capture(ctx, db.dbname, func(ctx context.Context) error {
		db.populate(ctx, query)

		var err error
		res, err = db.db.Query(enhanceQuery(ctx, query), args...)
		return err
	})

	return res, err
}

func (db *DB) QueryRow(ctx context.Context, query string, args ...interface{}) *sql.Row {
	var res *sql.Row

	Capture(ctx, db.dbname, func(ctx context.Context) error {
		db.populate(ctx, query)

		res = db.db.QueryRow(enhanceQuery(ctx, query), args...)
		return nil
	})

	return res
}

func (tx *Tx) Exec(ctx context.Context, query string, args ...interface{}) (sql.Result, error) {
	var res sql.Result

	err := Capture(ctx, tx.db.dbname, func(ctx context.Context) error {
		tx.db.populate(ctx, query)

		var err error
		res, err = tx.tx.Exec(enhanceQuery(ctx, query), args...)
		return err
	})

	return res, err
}

func (tx *Tx) Query(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) {
	var res *sql.Rows

	err := Capture(ctx, tx.db.dbname, func(ctx context.Context) error {
		tx.db.populate(ctx, query)

		var err error
		res, err = tx.tx.Query(enhanceQuery(ctx, query), args...)
		return err
	})

	return res, err
}

func (tx *Tx) QueryRow(ctx context.Context, query string, args ...interface{}) *sql.Row {
	var res *sql.Row

	Capture(ctx, tx.db.dbname, func(ctx context.Context) error {
		tx.db.populate(ctx, query)

		res = tx.tx.QueryRow(enhanceQuery(ctx, query), args...)
		return nil
	})

	return res
}

func (tx *Tx) Stmt(ctx context.Context, stmt *Stmt) *Stmt {
	return &Stmt{stmt.db, tx.tx.Stmt(stmt.stmt), stmt.query}
}

func (stmt *Stmt) Exec(ctx context.Context, args ...interface{}) (sql.Result, error) {
	var res sql.Result

	err := Capture(ctx, stmt.db.dbname, func(ctx context.Context) error {
		stmt.populate(ctx, stmt.query)

		var err error
		res, err = stmt.stmt.Exec(args...)
		return err
	})

	return res, err
}

func (stmt *Stmt) Query(ctx context.Context, args ...interface{}) (*sql.Rows, error) {
	var res *sql.Rows

	err := Capture(ctx, stmt.db.dbname, func(ctx context.Context) error {
		stmt.populate(ctx, stmt.query)

		var err error
		res, err = stmt.stmt.Query(args...)
		return err
	})

	return res, err
}

func (stmt *Stmt) QueryRow(ctx context.Context, args ...interface{}) *sql.Row {
	var res *sql.Row

	Capture(ctx, stmt.db.dbname, func(ctx context.Context) error {
		stmt.populate(ctx, stmt.query)

		res = stmt.stmt.QueryRow(args...)
		return nil
	})

	return res
}
