package clause

// Interface clause interface
type Interface interface {
	Name() string
	Build(Builder)
	MergeClause(*Clause)
}

// ClauseBuilder clause builder, allows to customize how to build clause
type ClauseBuilder func(Clause, Builder)

type Writer interface {
	WriteByte(byte) error
	WriteString(string) (int, error)
}

// Builder builder interface
type Builder interface {
	Writer
	WriteQuoted(field interface{})
	AddVar(Writer, ...interface{})
	AddError(error) error
}

// Clause
type Clause struct {
	Name                string // WHERE
	BeforeExpression    Expression
	AfterNameExpression Expression
	AfterExpression     Expression
	Expression          Expression
	Builder             ClauseBuilder
}

// Build build clause
func ( Clause) ( Builder) {
	if .Builder != nil {
		.Builder(, )
	} else if .Expression != nil {
		if .BeforeExpression != nil {
			.BeforeExpression.Build()
			.WriteByte(' ')
		}

		if .Name != "" {
			.WriteString(.Name)
			.WriteByte(' ')
		}

		if .AfterNameExpression != nil {
			.AfterNameExpression.Build()
			.WriteByte(' ')
		}

		.Expression.Build()

		if .AfterExpression != nil {
			.WriteByte(' ')
			.AfterExpression.Build()
		}
	}
}

const (
	PrimaryKey   string = "~~~py~~~" // primary key
	CurrentTable string = "~~~ct~~~" // current table
	Associations string = "~~~as~~~" // associations
)

var (
	currentTable  = Table{Name: CurrentTable}
	PrimaryColumn = Column{Table: CurrentTable, Name: PrimaryKey}
)

// Column quote with name
type Column struct {
	Table string
	Name  string
	Alias string
	Raw   bool
}

// Table quote with name
type Table struct {
	Name  string
	Alias string
	Raw   bool
}