package qgen

import "database/sql"

type transactionStmt struct {
	stmt     *sql.Stmt
	firstErr error // This'll let us chain the methods to reduce boilerplate
}

func newTransactionStmt(stmt *sql.Stmt, err error) *transactionStmt {
	return &transactionStmt{stmt, err}
}

func (stmt *transactionStmt) Exec(args ...interface{}) (*sql.Result, error) {
	if stmt.firstErr != nil {
		return nil, stmt.firstErr
	}
	return stmt.Exec(args...)
}

type TransactionBuilder struct {
	tx         *sql.Tx
	adapter    Adapter
	textToStmt map[string]*transactionStmt
}

func (b *TransactionBuilder) SimpleDelete(table string, where string) (stmt *sql.Stmt, err error) {
	res, err := b.adapter.SimpleDelete("", table, where)
	if err != nil {
		return stmt, err
	}
	return b.tx.Prepare(res)
}

// Quick* versions refer to it being quick to type not the performance. For performance critical transactions, you might want to use the Simple* methods or the *Tx methods on the main builder. Alternate suggestions for names are welcome :)
func (b *TransactionBuilder) QuickDelete(table string, where string) *transactionStmt {
	res, err := b.adapter.SimpleDelete("", table, where)
	if err != nil {
		return newTransactionStmt(nil, err)
	}

	stmt, ok := b.textToStmt[res]
	if ok {
		return stmt
	}
	stmt = newTransactionStmt(b.tx.Prepare(res))
	b.textToStmt[res] = stmt
	return stmt
}

func (b *TransactionBuilder) SimpleInsert(table string, columns string, fields string) (stmt *sql.Stmt, err error) {
	res, err := b.adapter.SimpleInsert("", table, columns, fields)
	if err != nil {
		return stmt, err
	}
	return b.tx.Prepare(res)
}

func (b *TransactionBuilder) QuickInsert(table string, where string) *transactionStmt {
	res, err := b.adapter.SimpleDelete("", table, where)
	if err != nil {
		return newTransactionStmt(nil, err)
	}

	stmt, ok := b.textToStmt[res]
	if ok {
		return stmt
	}
	stmt = newTransactionStmt(b.tx.Prepare(res))
	b.textToStmt[res] = stmt
	return stmt
}