module(..., package.seeall)

function GetColumns(connection, key, CF, firstCol, lastCol, rows, reverse, columnFn)
	--print("Getting columns of key ["..key:gsub("\n", "|").."]")
	--print("Getting columns from ["..firstCol:gsub("\n", "|").."] to ["..lastCol:gsub("\n", "|").."], reverse: "..tostring(reverse))
	local columns = connection:GetSliceRange(key, CF, "", { 
		slice_range = { start = firstCol, finish = lastCol, reversed = reverse or false, count = rows + 1 } 
	})
	for index, column in ipairs(columns) do
		if index <= rows then
			--print("Got column ["..column.name:gsub("\n", "|").."]")
			columnFn(column)
		else
			return column.name
		end
	end
end

function gsplit(s, sep, plain)
	local start = 1
	local done = false
	local function pass(i, j, ...)
		if i then
			local seg = s:sub(start, i - 1)
			start = j + 1
			return seg, ...
		else
			done = true
			return s:sub(start)
		end
	end
	return function()
		if done then return end
		if sep == '' then done = true return s end
		return pass(s:find(sep, start, plain))
	end
end

function GetSliceStart(ormDate, sliceSize)
	local dateTable = { year = ormDate:year(), month = ormDate:month(), day = ormDate:day(), hour = ormDate:hour(), min = ormDate:minute() } -- Seconds and fraction are always 0
	if sliceSize == "30Min" then
		dateTable.min = dateTable.min - (dateTable.min % 30)
	elseif sliceSize == "Hour" then
		dateTable.min = 0
	elseif sliceSize == "Day" then
		dateTable.min = 0
		dateTable.hour = 0
	elseif sliceSize == "Month" then
		dateTable.min = 0
		dateTable.hour = 0
		dateTable.day = 1
	elseif sliceSize == "Total" then
		dateTable.min = 0
		dateTable.hour = 0
	else -- 15Min is the default
		dateTable.min = dateTable.min - (dateTable.min % 15)
	end
	return LuaOrm.Date(dateTable)
end

function FormatDateForSlice(ormDate, sliceSize)
	if sliceSize == "30Min" then
		return ormDate:toString("%Y-%m-%d %H:%M").." - "..ormDate:add(0, 0, 0, 0, 30):toString("%H:%M")
	elseif sliceSize == "Hour" then
		return ormDate:toString("%Y-%m-%d %H:00").." - "..ormDate:add(0, 0, 0, 1):toString("%H:00")
	elseif sliceSize == "Day" then
		return ormDate:toString("%Y-%m-%d")
	elseif sliceSize == "Month" then
		return ormDate:toString("%Y-%m")
	elseif sliceSize == "Total" then
		return "Total"
	end
	-- 15Min is the default
	return ormDate:toString("%Y-%m-%d %H:%M").." - "..ormDate:add(0, 0, 0, 0, 15):toString("%H:%M")
end

function IncrementSlice(ormDate, sliceSize)
	if sliceSize == "30Min" then
		return ormDate:add(0, 0, 0, 0, 30)
	elseif sliceSize == "Hour" then
		return ormDate:add(0, 0, 0, 1)
	elseif sliceSize == "Day" then
		return ormDate:add(0, 0, 1)
	elseif sliceSize == "Month" then
		return ormDate:add(0, 1)
	end
	-- 15Min is the default
	return ormDate:add(0, 0, 0, 0, 15)
end

function DecrementSlice(ormDate, sliceSize)
	if sliceSize == "30Min" then
		return ormDate:add(0, 0, 0, 0, -30)
	elseif sliceSize == "Hour" then
		return ormDate:add(0, 0, 0, -1)
	elseif sliceSize == "Day" then
		return ormDate:add(0, 0, -1)
	elseif sliceSize == "Month" then
		return ormDate:add(0, -1)
	end
	-- 15Min is the default
	return ormDate:add(0, 0, 0, 0, -15)
end

function GetSlicesInBetween(firstSliceStart, lastSliceStart, sliceSize, reverse)
	local result = {}
	if sliceSize == "Total" then
		return result
	end
	if reverse then
		local sliceStart = DecrementSlice(lastSliceStart, sliceSize)
		while sliceStart:time() > firstSliceStart:time() do
			table.insert(result, sliceStart)
			sliceStart = DecrementSlice(sliceStart, sliceSize)
		end
	else
		local sliceStart = IncrementSlice(firstSliceStart, sliceSize)
		while sliceStart:time() < lastSliceStart:time() do
			table.insert(result, sliceStart)
			sliceStart = IncrementSlice(sliceStart, sliceSize)
		end
	end
	return result
end

function SliceSizeInMinutes(ormDate, sliceSize, dateTo)
	if sliceSize == "30Min" then
		return 30
	elseif sliceSize == "Hour" then
		return 60
	elseif sliceSize == "Day" then
		return 24*60
	elseif sliceSize == "Month" then
		return (ormDate:add(0, 1):time() - ormDate:time()) / 60
	elseif sliceSize == "Total" then
		return (dateTo:time() - ormDate:time()) / 60
	end
	-- 15Min is the default
	return 15
end

function CheckNaN(n)
	if type(n) ~= "number" then
		return n
	end
	if n == -1/0 or not (n < 1/0) or n == 0 then
		return 0
	end
	return n
end

function ShallowCopy(t)
	if type(t) ~= "table" then
		return t
	end
	local result = {}
	for k, v in pairs(t) do
		result[k] = v
	end
	return result
end
