package executor

import (
	"context"

	"github.com/everything-on-mysql/cassandra-on-mysql/pkg/cql/parser"
)

func (e *Executor) executeCreateKeyspace(ctx context.Context, user, password string, stmt *parser.CreateKeyspaceStatement) (*QueryResult, error) {
	e.ensureInternals()
	return e.ddl.executeCreateKeyspace(ctx, user, password, stmt)
}

func (e *Executor) executeDropKeyspace(ctx context.Context, user, password string, stmt *parser.DropKeyspaceStatement) (*QueryResult, error) {
	e.ensureInternals()
	return e.ddl.executeDropKeyspace(ctx, user, password, stmt)
}

func (e *Executor) executeCreateTable(ctx context.Context, user, password string, stmt *parser.CreateTableStatement) (*QueryResult, error) {
	e.ensureInternals()
	return e.ddl.executeCreateTable(ctx, user, password, stmt)
}

func (e *Executor) executeCreateType(ctx context.Context, user, password string, stmt *parser.CreateTypeStatement) (*QueryResult, error) {
	e.ensureInternals()
	return e.ddl.executeCreateType(ctx, user, password, stmt)
}

func (e *Executor) executeAlterType(ctx context.Context, user, password string, stmt *parser.AlterTypeStatement) (*QueryResult, error) {
	e.ensureInternals()
	return e.ddl.executeAlterType(ctx, user, password, stmt)
}

func (e *Executor) executeDropType(ctx context.Context, user, password string, stmt *parser.DropTypeStatement) (*QueryResult, error) {
	e.ensureInternals()
	return e.ddl.executeDropType(ctx, user, password, stmt)
}

func (e *Executor) executeDropTable(ctx context.Context, user, password string, stmt *parser.DropTableStatement) (*QueryResult, error) {
	e.ensureInternals()
	return e.ddl.executeDropTable(ctx, user, password, stmt)
}

func (e *Executor) executeTruncate(ctx context.Context, user, password string, stmt *parser.TruncateStatement) (*QueryResult, error) {
	e.ensureInternals()
	return e.ddl.executeTruncate(ctx, user, password, stmt)
}

func (e *Executor) executeAlterTable(ctx context.Context, user, password string, stmt *parser.AlterTableStatement) (*QueryResult, error) {
	e.ensureInternals()
	return e.ddl.executeAlterTable(ctx, user, password, stmt)
}

func (e *Executor) executeCreateIndex(ctx context.Context, user, password string, stmt *parser.CreateIndexStatement) (*QueryResult, error) {
	e.ensureInternals()
	return e.ddl.executeCreateIndex(ctx, user, password, stmt)
}

func (e *Executor) executeDropIndex(ctx context.Context, user, password string, stmt *parser.DropIndexStatement) (*QueryResult, error) {
	e.ensureInternals()
	return e.ddl.executeDropIndex(ctx, user, password, stmt)
}

func (e *Executor) executeCreateView(ctx context.Context, user, password string, stmt *parser.CreateMaterializedViewStatement) (*QueryResult, error) {
	e.ensureInternals()
	return e.ddl.executeCreateView(ctx, user, password, stmt)
}

func (e *Executor) executeDropView(ctx context.Context, user, password string, stmt *parser.DropMaterializedViewStatement) (*QueryResult, error) {
	e.ensureInternals()
	return e.ddl.executeDropView(ctx, user, password, stmt)
}

func (e *Executor) executeCreateTrigger(ctx context.Context, user, password string, stmt *parser.CreateTriggerStatement) (*QueryResult, error) {
	e.ensureInternals()
	return e.ddl.executeCreateTrigger(ctx, user, password, stmt)
}

func (e *Executor) executeDropTrigger(ctx context.Context, user, password string, stmt *parser.DropTriggerStatement) (*QueryResult, error) {
	e.ensureInternals()
	return e.ddl.executeDropTrigger(ctx, user, password, stmt)
}

func (e *Executor) validateDML(ctx context.Context, user, password string, stmt parser.Statement) error {
	e.ensureInternals()
	return e.dml.validateDML(ctx, user, password, stmt)
}

func (e *Executor) executeDMLStatement(ctx context.Context, exec sqlExecutor, user, password string, stmt parser.Statement, params []interface{}, plan *dmlPlan) (*QueryResult, error) {
	e.ensureInternals()
	return e.dml.executeDMLStatement(ctx, exec, user, password, stmt, params, plan)
}

func (e *Executor) buildDMLPlan(ctx context.Context, user, password string, stmt parser.Statement) (*dmlPlan, error) {
	e.ensureInternals()
	return e.dml.buildDMLPlan(ctx, user, password, stmt)
}

func (e *Executor) executeDMLPlan(ctx context.Context, exec sqlExecutor, plan *dmlPlan, params []interface{}) (*QueryResult, error) {
	e.ensureInternals()
	return e.dml.executeDMLPlan(ctx, exec, plan, params)
}

func (e *Executor) checkConditionalExists(ctx context.Context, exec sqlExecutor, cond dmlConditionPlan, params []interface{}) (bool, error) {
	e.ensureInternals()
	return e.dml.checkConditionalExists(ctx, exec, cond, params)
}

func (e *Executor) fetchConditionalResult(ctx context.Context, exec sqlExecutor, cond dmlConditionPlan, params []interface{}) (*QueryResult, error) {
	e.ensureInternals()
	return e.dml.fetchConditionalResult(ctx, exec, cond, params)
}

func (e *Executor) buildInsertPlan(ctx context.Context, user, password string, stmt *parser.InsertStatement) (*dmlPlan, error) {
	e.ensureInternals()
	return e.dml.buildInsertPlan(ctx, user, password, stmt)
}

func (e *Executor) buildUpdatePlan(ctx context.Context, user, password string, stmt *parser.UpdateStatement) (*dmlPlan, error) {
	e.ensureInternals()
	return e.dml.buildUpdatePlan(ctx, user, password, stmt)
}

func (e *Executor) buildConditionalUpdatePlan(ctx context.Context, user, password string, stmt *parser.UpdateStatement, whereConditions []equalityCondition, markerIndex map[parser.Expression]int, pkCols []string, columnTypes map[string]string) (*dmlPlan, error) {
	e.ensureInternals()
	return e.dml.buildConditionalUpdatePlan(ctx, user, password, stmt, whereConditions, markerIndex, pkCols, columnTypes)
}

func (e *Executor) buildDeletePlan(ctx context.Context, user, password string, stmt *parser.DeleteStatement) (*dmlPlan, error) {
	e.ensureInternals()
	return e.dml.buildDeletePlan(ctx, user, password, stmt)
}

func (e *Executor) primaryKeyColumns(ctx context.Context, user, password string, table *parser.TableName) ([]string, error) {
	e.ensureInternals()
	return e.dml.primaryKeyColumns(ctx, user, password, table)
}

func (e *Executor) buildFetchByPK(table *parser.TableName, columns []string, values []parser.Expression, pkCols []string, markerIndex map[parser.Expression]int, columnTypes map[string]string) (string, []int, error) {
	e.ensureInternals()
	return e.dml.buildFetchByPK(table, columns, values, pkCols, markerIndex, columnTypes)
}

func (e *Executor) buildWhereClause(conditions []equalityCondition, markerIndex map[parser.Expression]int, columnTypes map[string]string) (string, []int) {
	e.ensureInternals()
	return e.dml.buildWhereClause(conditions, markerIndex, columnTypes)
}

func (e *Executor) buildExistsSQL(table *parser.TableName, pkConditions, extra []equalityCondition, markerIndex map[parser.Expression]int, order *[]int, columnTypes map[string]string) string {
	e.ensureInternals()
	return e.dml.buildExistsSQL(table, pkConditions, extra, markerIndex, order, columnTypes)
}

func (e *Executor) buildFetchSQL(table *parser.TableName, columns []string, whereConditions []equalityCondition, markerIndex map[parser.Expression]int, order *[]int, columnTypes map[string]string) string {
	e.ensureInternals()
	return e.dml.buildFetchSQL(table, columns, whereConditions, markerIndex, order, columnTypes)
}

func (e *Executor) columnInfosForTableColumns(ctx context.Context, user, password string, table *parser.TableName, columns []string) ([]ColumnInfo, error) {
	e.ensureInternals()
	return e.dml.columnInfosForTableColumns(ctx, user, password, table, columns)
}

func (e *Executor) executeJSONInsert(ctx context.Context, exec sqlExecutor, user, password string, stmt *parser.InsertStatement, params []interface{}) (*QueryResult, error) {
	e.ensureInternals()
	return e.dml.executeJSONInsert(ctx, exec, user, password, stmt, params)
}

func (e *Executor) buildSelectPlan(ctx context.Context, user, password string, stmt *parser.SelectStatement, allowLimitBind bool, proxyFilter bool) (*selectPlan, error) {
	e.ensureInternals()
	return e.selectPlanner.buildSelectPlan(ctx, user, password, stmt, allowLimitBind, proxyFilter)
}

func (e *Executor) resolveSelectLimit(stmt *parser.SelectStatement, allowBind bool, suppressSQL bool) (*selectLimitDecision, error) {
	e.ensureInternals()
	return e.selectPlanner.resolveSelectLimit(stmt, allowBind, suppressSQL)
}

func (e *Executor) columnTypesForTable(ctx context.Context, user, password string, table *parser.TableName) (map[string]columnTypeInfo, error) {
	e.ensureInternals()
	return e.selectPlanner.columnTypesForTable(ctx, user, password, table)
}

func (e *Executor) buildSelectSQLWithToJSON(stmt *parser.SelectStatement, typeInfo map[string]columnTypeInfo, limitDecision *selectLimitDecision) (string, selectTransform, error) {
	e.ensureInternals()
	return e.selectPlanner.buildSelectSQLWithToJSON(stmt, typeInfo, limitDecision)
}

func (e *Executor) translateSelectExpr(expr parser.Expression, typeInfo map[string]columnTypeInfo) (string, *toJSONSpec, *castSpec, error) {
	e.ensureInternals()
	return e.selectPlanner.translateSelectExpr(expr, typeInfo)
}

func (e *Executor) toJSONSQLExpression(argSQL, cqlType, mysqlType string) (string, bool) {
	e.ensureInternals()
	return e.selectPlanner.toJSONSQLExpression(argSQL, cqlType, mysqlType)
}
