--
-- Library functions to support Lua code generated by Sq2Lua.exe
--

vlua = {}

-- Implements Squirrel clear table method
--
function vlua.clear(t)
    if type(t) == "table" then
        for k,v in pairs(t) do
            t[k] = nil
        end
    end
    return t
end

-- Implements Squirrel three way compare operator ( <=> )
--

function vlua.compare(a, b)
    if a < b then
        return -1
    elseif a > b then
        return 1
    else
        return 0
    end
end


-- Implements Squirrel in operator
--
function vlua.contains(t, k)
    return t ~= nil and type(t) == 'table' and t[k] ~= nil
end

-- Implements Squirrel slot delete operator
--
function vlua.delete(t, k)
    local previous = nil
    if vlua.contains(t, k) then
        previous = t[k]
        t[k] = nil
    end
    return previous
end

-- Implements Squirrel clone operator
--
function vlua.clone(t)
    if not type(t) == 'table' then
        return nil
    end
    local result = {}
    for i, v in pairs(t) do
        result[i] = v
    end
    setmetatable(result, getmetatable(t))
    return result
end

-- Implements Squirrel rawdelete library function
--
function vlua.rawdelete(t, k)
    -- TODO: should we temporarily nil out metatable of t before calling delete?
    --
    return vlua.delete(t, k)
end

-- Implements Squirrel rawin library function
--
function vlua.rawin(t, k)
    -- TODO: should we temporarily nil out metatable of t before calling in?
    --
    return vlua.contains(t, k)
end

-- Implements Squirrel find method for tables and strings
-- (o, substr, [startidx]) for strings
-- (o, value) for tables
--
function vlua.find(o, arg1, ...)
    local arg = {...}
    if type(o) == 'string' then
        local start = 1
        if #arg == 1 then
            start = arg[1]
        end
		if arg1 == nil then
			local msg = "vlua.find(" .. o .. ", nil)"
			print( msg )
			ScriptAssert( false, msg )
			return nil
		end
        local ms, me = string.find(o, arg1, start, true)
        if ms then
            return ms
        end
    elseif type(o) == 'table' then
        for i, v in pairs(o) do
            if arg1 == v then
                return i
            end
        end
    end

    return nil
end

-- Implements Squirrel slice method for tables and strings
--
function vlua.slice(o, starti, ...)
    local arg = {...}
    local olen = #o
    -- Need to add one since below code is inclusive
    local endi = olen + 1
    if #arg == 1 then
        if arg[1] < 0 then
            endi = endi + arg[1]
        else
            endi = arg[1]
        end
        -- need to subtract on as code below is inclusive and any argument we got assumed not inclusive
        endi = endi - 1
    end
    if starti < 0 then
        -- need to add one to length as they are asking for last abs(starti) chars and we are one based in Lua
        -- For example if #o == 6 and starti == -1 then we want starti == 6 to get last char (6 == #o + 1 - 1)
        starti = olen + 1 + starti
    end

    if type(o) == 'string' then
        return string.sub(o, starti, endi)
    elseif type(o) == 'table' then
        local result = {}
        for i = starti, endi do
            table.insert(result, o[i])
        end
        return result
    end

    return nil
end

-- Implements Squirrel reverse method for tables
--
function vlua.reverse(o)
    local len = #o
    for i = 1, len / 2 do
        local tmp = o[i]
        o[i] = o[len + 1 - i]
        o[len + 1 - i] = tmp
    end
    return o
end

-- Implements Squirrel resize method for tables
--
function vlua.resize(o, size, ...)
    local arg = {...}
    local fill = nil
    if #arg == 1 then
        fill = arg[1]
    end
    local cur_size = #o;
    if cur_size >= size then
        for i = size + 1, cur_size do
            table.remove(o)
        end
    else
        if not fill then
           error('Fill value cannot be nil')
        end
        for i = cur_size + 1, size do
            table.insert(o, fill)
        end
    end
    return o
end

-- Implements Squirrel extend method for tables
--
function vlua.extend(o, ary)
    if #ary <= 0 then
        return
    end

    for i = 1, #ary do
        table.insert(o, ary[i])
    end
    return o
end

-- Implements Squirrel map method for tables
--
function vlua.map(o, fn)
    local res = {}
    for i, v in pairs(o) do
        res[i] = fn(v)
    end
    return res
end

-- Implements Squirrel reduce method for tables
--
function vlua.reduce(o, fn)
    if #o <= 0 then
        return nil
    elseif #o == 1 then
        return o[1]
    end

    local res = o[1]
    for i = 2, #o do
        res = fn(res, o[i])
    end
    return res
end

-- Implements tableadd function vlua.to support += paradigm used in Squirrel
--
function vlua.tableadd(t1, t2)
    for k,v in pairs(t2) do
        t1[k] = v
    end
    return t1
end

-- Implements Squirrel split function for strings
--
function vlua.split(str, sep)
    if type(str) ~= 'string' or type(sep) ~= 'string' then
        return nil
    end

    local res_ary = {}
    local cur = nil

    for i = 1, #str do
        local ch = string.byte(str, i)
        local hit = false
        for j = 1, #sep do
            if ch == string.byte(sep, j) then
                hit = true
                break
            end
        end
        if hit then
            if cur then
                table.insert(res_ary, cur)
            end
            cur = nil
        elseif cur then
            cur = cur .. string.char(ch)
        else
            cur = string.char(ch)
        end
    end

    if cur then
        table.insert(res_ary, cur)
    end

    return res_ary
end

-- Safe Ternary operator. The Lua version will return the wrong value if the value if true is nil 
--
function vlua.select( conditional, valueIfTrue, valueIfFalse )
	if ( conditional ) then
		return valueIfTrue
	end
	return valueIfFalse
end