---------- ---------- ---------- ---------- ---------- 
-- Name: string.ToTable( String )
-- Desc: Converts every char in a string to a table
---------- ---------- ---------- ---------- ---------- 
function string.toTable( String )
	local Table = {}
	
	for i = 1, string.len( String ) do
		table.insert( Table, string.sub( String, i, i ) )
	end
	
	return Table
end

---------- ---------- ---------- ---------- ---------- 
-- Name: string.Explode( Seperator, String )
-- Desc: Takes a string and turns it into a table
-- Examples:
-- 	local S = string.explode( " ", "Seperate this string")
--	S[1] = "Seperate"
--	S[2] = "this"
--	S[3] = "string"
---------- ---------- ---------- ---------- ---------- 
function string.explode( Seperator, String )
	
	if ( Seperator == "" ) then
		return string.ToTable( String )
	end
	
	local Table = {}
	local Pos = 0
	
	while true do
		CurPos = string.find( String, Seperator, Pos, true )
		
		if not ( StrPos ) then
			table.insert( Table, string.sub( String, Pos, CurPos - 1 ) ) 
			Pos = CurPos + 1
		else
			table.insert( Table, string.sub( String, Pos ) )
			
			break
		end
	end
	
	return Table
end

---------- ---------- ---------- ---------- ---------- 
-- Name: string.Implode( Seperator, Table )
-- Desc: Alias of table.concat
---------- ---------- ---------- ---------- ---------- 
function string.implode( Seperator, Table )
	return table.concat( Table, Seperator )
end

---------- ---------- ---------- ---------- ---------- 
-- Name: string.FormattedTime( TimeInSeconds [, Format] )
-- Desc: Given a time in seconds, returns formatted time 
-- 	If 'Format' is not specified the function returns a table  
-- 	conatining values for hours,  mins,  secs,  ms 
-- 
-- Examples: 
--	string.FormattedTime( 123.456, "%02i:%02i:%02i")	==> "02:03:45" 
-- 	string.FormattedTime( 123.456, "%02i:%02i")		==> "02:03" 
-- 	string.FormattedTime( 123.456, "%2i:%02i")		==> " 2:03" 
-- 	string.FormattedTime( 123.456 )				==> {h = 0, m = 2, s = 3, ms = 45} 
---------- ---------- ---------- ---------- ---------- 
function string.formattedTime( TimeInSeconds, Format )
	TimeInSeconds = TimeInSeconds or 0
	
	local i = math.floor( TimeInSeconds )
	local h, m, s, ms = ( i/3600 ), 
						( i/60 ) - ( math.floor( i/3600 ) * 3600 ), 
						TimeInSeconds - ( math.floor( i/60 ) * 60 ), 
						( TimeInSeconds - i ) * 100
			
	if ( Format ) then
		return string.format( Format, m, s, ms )
	else 
		return { h = h, m = m, s = s, ms = ms }
	end
end

---------- ---------- ---------- ---------- ---------- 
-- Name: string.Trim( String [, Char] ) 
-- Desc: Removes leading and trailing spaces from a string
--	Optionally pass char to trim that character from the ends instead of space
---------- ---------- ---------- ---------- ---------- 
function string.trim( String, Char )
	Char = Char or "%s"
	
	return string.gsub( String, "^" .. Char .. "*(.-)" .. Char .. "*$", "%1" )
end

function string.localizeBigNumber(value, locale)

	value = math.floor(value)
	locale = locale or "en"
	
	if value == 0 then
		return "0"
	end
	
	if locale == "en" then
		local sign = ""
		if value < 0 then
			sign = "-"
			value = -value
		end
		local parts = ""
		while value >= 1000 do
			local subValue = (value % 1000)
			if subValue < 10 then
				parts = ",00" .. subValue .. parts
			elseif subValue < 100 then
				parts = ",0" .. subValue .. parts
			else
				parts = "," .. subValue .. parts
			end
				
			value = math.floor(value / 1000)
		end
		
		return sign .. value .. parts
	end

end

function string.stripExtension(filename)
	for i=0,string.len(filename) do
		local theChar = string.sub(filename, string.len(filename)-i, string.len(filename)-i)
		if theChar == "." then
			return string.sub(filename, 1, string.len(filename)-i-1)
		end
	end
	return filename
end

function string.stripPath(path)
	for i=0,string.len(path) do
		local theChar = string.sub(path, string.len(path)-i, string.len(path)-i)
		if theChar == "/" or theChar == "\\" then
			return string.sub(path, string.len(path)-i+1)
		end
	end
	return path
end

function string.indexToNumberAndLowerCaseKey(index)
	if index <= 9 then
		return 48 + index
	elseif index == 10 then
		return 48
	elseif index > 10 then
		return 64 + (index-10)
	end
end

function string.randomText(len)
	local t = ""
	for i=1,len do
		t = t..string.char(math.random(65,90))
	end
	return t
end

function string.split(str, pat)
   local t = {}
   local fpat = "(.-)" .. pat
   local last_end = 1
   local s, e, cap = str:find(fpat, 1)
   while s do
      if s ~= 1 or cap ~= "" then
		table.insert(t,cap)
      end
      last_end = e+1
      s, e, cap = str:find(fpat, last_end)
   end
   if last_end <= #str then
      cap = str:sub(last_end)
      table.insert(t, cap)
   end
   return t
end

function string.splitParameters(str, pat)
   return unpack(string.split(str, pat))
end

function string.optional_concat(str, con, spacer)
	if str and str ~= "" then
		return str..spacer..con
	else
		return con
	end
end


local code_unit1, code_unit2, code_unit3, code_unit4

local space_byte = string.byte(" ")
local function string_error(msg)
	return space_byte, 1
end
function string.getCodePoint(text, start)
	code_unit1 = text:byte(start)
	if (code_unit1 < 0x80) then
		--return codepoint and stride
		return code_unit1, 1
	elseif (code_unit1 < 0xC2) then
		-- continuation or overlong 2-byte sequence
		return string_error("UTF8 ERROR1")
	elseif (code_unit1 < 0xE0) then
		-- 2-byte sequence
		code_unit2 = text:byte(start+1)
		if not code_unit2 or (bit.band(code_unit2, 0xC0) ~= 0x80) then return string_error("UTF8 ERROR2") end
		--return codepoint and stride
		return bit.lshift(code_unit1, 6) + code_unit2 - 0x3080, 2
	elseif (code_unit1 < 0xF0) then
		-- 3-byte sequence
		code_unit2 = text:byte(start+1)
		if not code_unit2 or (bit.band(code_unit2, 0xC0) ~= 0x80) then return string_error("UTF8 ERROR3") end
		if (code_unit1 == 0xE0 and code_unit2 < 0xA0) then return string_error("UTF8 ERROR4") end -- overlong
		code_unit3 = text:byte(start+2)
		if not code_unit3 or (bit.band(code_unit3, 0xC0) ~= 0x80) then return string_error("UTF8 ERROR5") end
		--return codepoint and stride
		return bit.lshift(code_unit1, 12) + bit.lshift(code_unit2, 6) + code_unit3 - 0xE2080, 3
	elseif (code_unit1 < 0xF5) then
		-- 4-byte sequence
		code_unit2 = text:byte(start+1)
		if not code_unit2 or (bit.band(code_unit2, 0xC0) ~= 0x80) then return string_error("UTF8 ERROR6") end
		if (code_unit1 == 0xF0 and code_unit2 < 0x90) then return string_error("UTF8 ERROR7") end -- overlong
		if (code_unit1 == 0xF4 and code_unit2 >= 0x90) then return string_error("UTF8 ERROR8") end -- > U+10FFFF
		code_unit3 = text:byte(start+2)
		if not code_unit3 or (bit.band(code_unit3, 0xC0) ~= 0x80) then return string_error("UTF8 ERROR9") end
		code_unit4 = text:byte(start+3)
		if not code_unit4 or (bit.band(code_unit4, 0xC0) ~= 0x80) then return string_error("UTF8 ERROR10") end
		--return codepoint and stride
		return bit.lshift(code_unit1, 18) + bit.lshift(code_unit2, 12) + bit.lshift(code_unit3, 6) + code_unit4 - 0x3C82080, 4
	else
		-- > U+10FFFF
		return string_error("ERROR11")
	end
end

function string.getCodePointChar(text, start)
	local t_len = string.len(text)			
	if t_len >= start then
		local schar,t_stride = string.getCodePoint(text, start)
		return string.char(schar), t_stride
	else
		return "", 1
	end
end

local function percent(num)
	return num.."%" --void default
end

function string.getPercent(v,m)
	return percent(math.max(0,math.round(v/(m or 1)*100)))
end
