local string = string
local table = table
local error = error
local tostring = tostring
local next = next
local type = type

module("LuaOrm.DBMS.Sqlite3")

-- properties
supportsNolock = false
cursorSupportsProperties = false
identifierQuoteLeft = "["
identifierQuoteRight = "]"

--
-- printf-like function that also takes care of quoting identifiers (table names, etc)
--
local left_quote = "["
local right_quote = "]"

function Format (s, ...)
	local index = 1
	local args = {...}
	
	s = s:gsub("(%%.)", function(capture)
		local value = args[index]
		index = index + 1
		if value then
			if capture == "%Q" then
				return left_quote .. tostring(value) .. right_quote
			elseif capture == "%s" then
				return tostring(value)
			elseif capture == "%d" then
				return tonumber(value)
			end
		end
		return nil
	end)
	
	return s
end

function GetTablePrimaryKey(conn, tableName)
	local rows = {}
	local index = 0
	local sql = string.format([[PRAGMA table_info(%s)]], tableName)
	local cursor, err = conn:execute(sql)
	if not cursor then error(err) end
	local row = cursor:fetch({}, "a")
	while row and row.pk == 1 do
		table.insert(rows, #rows, row.name)
		row = cursor:fetch(row, "a")
	end
	cursor:close()
	return rows
end

-- esta funcion la copie de SqlServer, seguro que aca aplica distinto
function IsForeignKeyViolation(code)
	LogDebug("Error code beign checked is:"..tostring(code))
	if (tostring(code) == "547") then
		return true
	end
	return false
end


function GetTableMetadata(conn, tableName)
	local rows = {}
	local metaData = {}
	local sql = string.format([[PRAGMA table_info(%s)]], tableName)
	local cursor, err = conn:execute(sql)
	if not cursor then error(err) end
	local row, fetched = cursor:fetch({}, "a")
	while row do
		local colinfo = {
			name = row.name,
			type = string.lower(string.match(row.type, "(%a+)")),
			-- hay autonumber en sqlite ?
			--isAutoNumber = ((string.match(row["TYPE_NAME"], "%a+%p+%s+(%a+)") == "identity") and true) or false,
			length = string.match(row.type, "%a+%((%d+)%)"),
			nullable = not (row.type == 1)
		}
		metaData[#metaData + 1] = colinfo
		metaData[colinfo.name] = colinfo
		row = cursor:fetch(row, "a")
	end
	cursor:close()
	return metaData
end


function GetForeignKeysFrom(connection, model, fromModel)
	--print("GetForeignKeysFrom", model.tableName, fromModel.tableName)
	local rows = {}
	local conn = connection
	local foreignKeys = {}
	local sql = string.format([[PRAGMA foreign_key_list(%s)]], fromModel.tableName)
	local cursor, err = conn:execute(sql)
	if not cursor then error(err) end
	if cursor == 0 then
		-- if there are no FKs then PRAGMA returns 0
		return nil
	end
	local tableName = model.tableName
	local row = cursor:fetch({}, "a")
	while row do
		if row.table == tableName then
			foreignKeys[row.to] = row.from
		end
		row = cursor:fetch(row, "a")
	end
	if next(foreignKeys) == nil then
		foreignKeys = nil
	end
	cursor:close()
	return foreignKeys
end

function GetForeignKeysTo(connection, model, toModel)
	--print("GetForeignKeysTo", model.tableName, toModel.tableName)
	local rows = {}
	local conn = connection
	local foreignKeys = {}
	local sql = string.format([[PRAGMA foreign_key_list(%s)]], model.tableName)
	local cursor, err = conn:execute(sql)
	if not cursor then error(err) end
	if cursor == 0 then
		-- if there are no FKs then PRAGMA returns 0
		return nil
	end
	local tableName = toModel.tableName
	local row = cursor:fetch({}, "a")
	while row do
		if row.table == tableName then
			foreignKeys[row.to] = row.from
		end
		row = cursor:fetch(row, "a")
	end
	if next(foreignKeys) == nil then
		foreignKeys = nil
	end
	cursor:close()
	return foreignKeys
end

function BeginTransaction (conn)
	return conn:execute("BEGIN;")
end

function Commit (conn)
	return conn:commit()
end

function Rollback (conn)
	return conn:rollback()
end
