--****************C++交互的关键字符*************************--
--错误信息
g_errorStr = ""
--全局数组表
sz={}
--**************************************************--


--变量表
local g_variableTable= {}
--常量表
local g_constTable= {}
--场景表
local g_sceneTable= {}
--区域表
local g_areaTable= {}
--时间段表
local g_timeRangeTable= {}
--自适应场景表
local g_adaptSceneTable={}
--设备切换表
local g_deviceTable={}

--上下文数据表
local g_contextDataTable={}
--延时处理的数据
local g_contextDelayArray = {}
local g_savePos = -1


-- 获取字符串的长度（任何单个字符长度都为1）
function getStringLength(inputstr)
    if not inputstr or type(inputstr) ~= "string" or #inputstr <= 0 then
        return nil
    end
    local length = 0  -- 字符的个数
    local i = 1
    while true do
        local curByte = string.byte(inputstr, i)--根据首字节的大小确定
        local byteCount = 1
        if curByte > 239 then --11110xxx
            byteCount = 4  -- 4字节字符
        elseif curByte > 223 then --1110xxxx
            byteCount = 3  -- 3字节字符
        elseif curByte > 128 then  --110xxxxx
            byteCount = 2  -- 双字节字符
        else
            byteCount = 1  -- 单字节字符
        end
        -- local char = string.sub(inputstr, i, i + byteCount - 1)
        -- print(char)  -- 打印单个字符
        i = i + byteCount
        length = length + 1
        if i > #inputstr then
            break
        end
    end
    return length
end

--打印table信息
function PrintTable(name,pTable)
	local i = 0
	print("*****",name,"*****");
		for k,v in pairs(pTable) do 
		 print("k = ",k," v = ",v)
			i = i+1
		end
	print("count =",i);
	print("*************");
	return i
end

function CountTable(pTable)
	local i = 0
	for k,v in pairs(pTable) do 
	 i=i+1
	end
	return i
end


--规则引擎main()
function LuaGlossary(str,datatable)
	sz = datatable
	--PrintTable("sz",sz)
	local strTmp = "string.format("..str..")"
	local exeStr = "tmp="..strTmp..";return tmp"
	--print("format:",exeStr)
	strTTMP = load(exeStr)()
	return strTTMP
end

--初始化自定义数据表函数
function UserDataInit0(strJSON)
    --print(strJSON)
   
   local lua_objcet = cjson.decode(strJSON)
   
   --变量表
   g_variableTable = lua_objcet["variableTable"]
   --常量表
   g_constTable = lua_objcet["constTable"]
   --场景表
   g_sceneTable = lua_objcet["sceneTable"]
   --区域表
   g_areaTable = lua_objcet["areaTable"]
   --时间段表
   g_timeRangeTable = lua_objcet["timeRangeTable"]
   --设备切换表
   g_deviceTable = lua_objcet["deviceTable"]
   --自适应场景表 
   g_adaptSceneTable = lua_objcet["adaptSceneTable"]
  
	--local n = ctestLuaAdd("1","2")
	--print("n=",n)
	
	--local n1 = myTest.cFuncAdd1(1,2)
	--print("n1=",n1)
	
	--local n2 = myTest.cFuncAdd2(1,2)
	--print("n2=",n2)
  
 --PrintTable(userTable)
  
end

--上下文数据，家居传递的是当前节点的信息
function contextDataFunc(nodeStr)
	g_contextDataTable = cjson.decode(nodeStr)
	--PrintTable("contextDataTable",g_contextDataTable)
end


--上下文数据，家居传递的是延时处理的节点信息
function contextDelayFunc(nodeStr)
	g_contextDelayArray = cjson.decode(nodeStr)
	g_contextDataTable["Pos"] = g_savePos
end

function contextStartPos(sizeStr)
	g_savePos = g_contextDataTable["Pos"] 
end

--上下文数据，家居传递的是延时处理的节点信息，更新pos
function contextDelayPosFunc(sizeStr)
	g_contextDataTable["Pos"] = tonumber(sizeStr) + g_contextDataTable["Pos"]
	--print("g_contextDelayStr:",g_contextDelayStr);
end



--判断是否是字符串外层双引号
function isNumber(s1)
	local result
	
	local constValue = tonumber(s1)
	if(constValue ~=nil) then
		result = "Const"
	else
		--print("str1:",string.find(s1,"\"",1))
		--print("str2:",string.find(s1,"\"",string.len(s1)))
		if(string.find(s1,"\"",1) == 1 and string.find(s1,"\"",string.len(s1)) == string.len(s1)) then
			result = "Const"
		end
	end
	
	return result
end


--通过名称查找时间段表的数据
function coverFindTimeRangeTable(name)
	local result = ""
	g_errorStr = ""
	 for i=1,#(g_timeRangeTable) do
		local nameTmp = g_timeRangeTable[i]["name"]
		if  (nameTmp == name) then 
			result = g_timeRangeTable[i]["value"]
			return result
		end
     end
	 g_errorStr = name.."在时间段表中不存在"
	return result
end



function getTokenType(s0,s1,s2)
	local result
	if (s2 == "Identifer") then
		--是否是常量值
		local constValue = isNumber(s1)
		if(constValue ~=nil) then
			result = "Const"
		else
			--是否是变量
			local name = variableTableFindTypeAndName(s1)
			if(name ~= nil)then
				result = "Variable"
			else 
				--不是变量，查找是否是s0定义的值描述别名
				result = variableTableFindValueDes(s0,s1)
			end
		end
		
	elseif(s2 == "Variable") then
		--检查下变量表 是否有s1变量
		local name = variableTableFindTypeAndName(s1)
		if(name ~= nil)then
			result = "Variable"
		else 
			result = "Identifer"
		end
	else
		result = s2
	end
	
	return result
end



function getCancelDelayGlossaryArray(s1,pos)
	--lua不支持中文的正则匹配，因此替换中文字符，再找数字
     local tmps1 = string.gsub(s1, "[\192-\255][\128-\191]*","k")
	local str1,str2= string.match(tmps1,"(%a+)(%d+)")
	print("str1:",str1)
	print("str2:",str2)
	local resultJson ={}
	if (str1 ~= nil ) then
		local tmpPos =  pos + getStringLength(str1)
		resultJson[1]={
			["SrcValue"] = str2,
			["TokenType"] = "DelayGlossaryID",
			["Pos"] = tmpPos,
			["Children"] = {}
		}
	end
	return resultJson
end

--拆分语句
function getTokenList1(s1,s2)
	--local tmpTable = {s1}
	--local count = CountTable(tmpTable)

	local resultJson ={}
	
	local tmpPos = g_contextDataTable["Pos"]
	local tokenType = getTokenType(s1,s1,s2)
	
	if(tokenType == "CancelDelayGlossary" ) then
		--取消延时的特殊处理

		local CancelDelayGlossary = getCancelDelayGlossaryArray(s1,tmpPos)

		resultJson={
			["SrcValue"] = s1,
			["TokenType"] = tokenType,
			["Pos"] = tmpPos,
			["Children"] = CancelDelayGlossary
		}
		
	else
		resultJson = {
			["SrcValue"] = s1,
			["TokenType"] = tokenType,
			["Pos"] = tmpPos,
			["Children"] = {}
		}
	end
	
	local jsonStr = cjson.encode(resultJson);
	return jsonStr
end





function getDelayGlossaryArray(s1,pos)
	print("s1:",s1)
	--lua不支持中文的正则匹配，因此替换中文字符，再找数字
     local tmps1 = string.gsub(s1, "[\192-\255][\128-\191]*","k")
	print("tmps1:",tmps1)
	local str1,str2,str3,str4= string.match(tmps1,"(%a+)(%d+)(%a+)(%d+)%a+")
	
	print("str1:",str1)
	print("str2:",str2)
	print("str3:",str3)
	print("str4:",str4)
	local resultJson ={}
	if (str1 ~= nil ) then
		local tmpPos =  pos + getStringLength(str1)
		resultJson[1]={
			["SrcValue"] = str2,
			["TokenType"] = "DelayGlossaryID",
			["Pos"] =tmpPos,
			["Children"] = {}
		}
		
		 tmpPos = tmpPos + getStringLength(str2) +getStringLength(str3)
		
		resultJson[2]={
			["SrcValue"] = str4,
			["TokenType"] = "Const",
			["Pos"] = tmpPos,
			["Children"] = {}
		}
	end
	return resultJson
end

function getTokenList2(s1,s2,s3,s4)
	--local tmpTable = {s1,s2,s3,s4}
	--local count = CountTable(tmpTable)
	
	local tmpPos = g_contextDataTable["Pos"]
	
	local tokenType1 = getTokenType(s1,s1,s2)
	local tokenType2 = getTokenType(s1,s3,s4)
	
	local ChildrenArray = {}
	
    --ChildrenArray[2] = g_contextDelayArray
	print("getTokenList2")
	if(tokenType1 == "DelayGlossary" ) then
		--延时的主语句的特殊处理
		print("DelayGlossary")
		local DelayGlossaryArray = getDelayGlossaryArray(s1,tmpPos)

		ChildrenArray[1]={
			["SrcValue"] = s1,
			["TokenType"] = tokenType1,
			["Pos"] = tmpPos,
			["Children"] = DelayGlossaryArray
		}
		
	else
		ChildrenArray[1]={
			["SrcValue"] = s1,
			["TokenType"] = tokenType1,
			["Pos"] = tmpPos,
			["Children"] = {}
		}
	end
	
	tmpPos =tmpPos+getStringLength(s1)
	
	if (tokenType2== "Expression")then
		--延时的子语句的特殊处理
		--根据g_contextDelayArray的多个数据结构在组合到ChildrenArray里面
		--PrintTable("g_contextDelayArray",g_contextDelayArray)
		for i=1,#(g_contextDelayArray) do
			ChildrenArray[1+i] = g_contextDelayArray[i]
		end
	else 
		ChildrenArray[2]={
			["SrcValue"] = s3,
			["TokenType"] = tokenType2,
			["Pos"] =tmpPos,
			["Children"] = {}
		}
	end
	
	
	
	tmpPos =tmpPos+getStringLength(s3)
	
	local resultJson = {
		["SrcValue"] = s1..s3,
		["TokenType"] = "Expression",
		["Pos"] = g_contextDataTable["Pos"],
		["Children"] = ChildrenArray
	}
	
	local jsonStr = cjson.encode(resultJson);
	
	return jsonStr
end

function getTokenList(s1,s2,s3,s4,s5,s6)
	local tmpTable = {s1,s2,s3,s4,s5,s6}
	local count = CountTable(tmpTable)
	local jsonStr
	
	local tokenType1 = getTokenType(s1,s1,s2)
	local tokenType2 = getTokenType(s1,s3,s4)
	local tokenType3 = getTokenType(s1,s5,s6)

	
	if(count <= 2) then
		jsonStr = getTokenList1(s1,s2)
	elseif(count <= 4)  then
		jsonStr = getTokenList2(s1,s2,s3,s4)
	else
		local tmpPos = g_contextDataTable["Pos"]
		local ChildrenArray = {}
		ChildrenArray[1]={
			["SrcValue"] = s1,
			["TokenType"] = tokenType1,
			["Pos"] = tmpPos,
			["Children"] = {}
		}
		
		tmpPos =tmpPos+getStringLength(s1)
		
		ChildrenArray[2]={
			["SrcValue"] = s3,
			["TokenType"] = tokenType2,
			["Pos"] =tmpPos,
			["Children"] = {}
		}
		
		tmpPos =tmpPos+getStringLength(s3)
		
		ChildrenArray[3]={
			["SrcValue"] = s5,
			["TokenType"] = tokenType3,
			["Pos"] =tmpPos,
			["Children"] = {}
		}
		
		
		local resultJson = {
			["SrcValue"] = s1..s3..s5,
			["TokenType"] = "Expression",
			["Pos"] = g_contextDataTable["Pos"],
			["Children"] = ChildrenArray
		}
		jsonStr = cjson.encode(resultJson);
	end
	return jsonStr
end

--根据变量名在变量数据表找数据类型
function variableTableFindTypeAndDataType(s1)
	 local dataType
	 for i=1,#(g_variableTable) do
		local  name = g_variableTable[i]["name"]
		if  (name == s1) then 
			dataType = g_variableTable[i]["dataType"]
			return dataType
		end
     end
	 g_errorStr = "变量名("..s1..")在变量表中未找到相应数据类型"
	 return dataType
end

function coverEquals(s1,s2)
	local resultStr = ""
	local s2Str = s2
	local n = g_contextDataTable["CutType"]
	
	--判断s1的数据类型 bool 要把 s2的0变成false,其他变true
	local dataType = variableTableFindTypeAndDataType(s1);
	if (dataType == "bool") then
		local boolNum = tonumber(s2)
		if(boolNum == 0)then
			s2Str ="false"
		else
			s2Str ="true"
		end
	end

	if n==0 then
		--条件
		resultStr = s1.."=="..s2Str
	else
		--结果
		resultStr = s1.."="..s2Str
	end 

	
	return resultStr
end


function coverOperator(s1,s2,operator)
	--错误码初始化
	g_errorStr = ""
	
	
	local resultStr = ""
	local s2Str = s2
	--判断s1的数据类型 bool 要把 s2的0变成false,其他变true
	local dataType = variableTableFindTypeAndDataType(s1);
	if (dataType == "bool") then
		local boolNum = tonumber(s2)
		if(boolNum == 0)then
			s2Str ="false"
		else
			s2Str ="true"
		end
	end
	
	
	
	resultStr = s1..operator..s2Str
	
	return resultStr
end


function coverWeekday(str)
	local result = ""
	g_errorStr = ""
	if (str=="星期一") then
		result = "WeekDay(1)==true"
	elseif (str=="星期二") then
		result = "WeekDay(2)==true"
	elseif (str=="星期三") then
		result = "WeekDay(4)==true"
	elseif (str=="星期四") then
		result = "WeekDay(8)==true"
	elseif (str=="星期五") then
		result = "WeekDay(16)==true"
	elseif (str=="星期六") then
		result = "WeekDay(32)==true"
	elseif (str=="星期日") then
		result = "WeekDay(64)==true"
	elseif (str=="星期天") then
		result = "WeekDay(64)==true"
	elseif (str=="周末") then
		result = "WeekDay(96)==true"
	elseif (str=="工作日") then
		result = "WeekDay(31)==true"
	else 
		result = ""
		g_errorStr = str.."是无效的星期术语"
	end

	
	
	return result
end

function areaLed(s1,value)
	g_errorStr = ""
	local resultStr = ""
	local n = g_contextDataTable["CutType"]

	--通过区域名称找区域编号
	local tmpNo = -1
	for i=1,#(g_areaTable) do
		local name = g_areaTable[i]["name"]
		if  (name == s1) then 
			tmpNo = g_areaTable[i]["no"]
			break
		end
	end
	
	if(tmpNo == -1)then
		--g_errorStr = s1.."通过区域表未找到对应的区域编号"
		return resultStr
	else
		--通过区域编号找负载类型是“灯”的变量名称
		local tmpTable = {}
		for i=1,#(g_variableTable) do
			local areaNo = g_variableTable[i]["areaNo"]
			local loadType = g_variableTable[i]["loadType"]
			if  (areaNo == tmpNo and loadType == "灯") then 
				table.insert(tmpTable,g_variableTable[i]["name"])
			end
		end
		
		local num = CountTable(tmpTable)
		if (num ==0) then
			g_errorStr = "负载类型为灯的变量未找到"
			return resultStr
		end

		if(n == 0) then
			--条件
			for i=1,#(tmpTable) do
				local Str = tmpTable[i].."=="..value
				if(i==#tmpTable) then
					resultStr = Str..resultStr
				else
					resultStr = resultStr.."&&"..Str
				end
			end
		else
			--结果
			for i=1,#(tmpTable) do
				local Str = tmpTable[i].."="..value
				if(i==#tmpTable) then
					resultStr = Str..resultStr
				else
					resultStr = resultStr..";"..Str
				end
			end
			
		end
	end
	
	return resultStr
end

function allLen(value)
	g_errorStr = ""
	local resultStr = ""
	local n = g_contextDataTable["CutType"]
	
	--找到所有灯
	local tmpTable = {}
	for i=1,#(g_variableTable) do
		local loadType = g_variableTable[i]["loadType"]
		if  (loadType == "灯") then 
			table.insert(tmpTable,g_variableTable[i]["name"])
		end
	end
	
	local num = CountTable(tmpTable)
	if (num ==0) then
		g_errorStr = "负载类型为灯的变量未找到"
		return resultStr
	end
	
	if(n == 0) then
		--条件
		for i=1,#(tmpTable) do
			local Str = tmpTable[i].."=="..value
			if(i==#tmpTable) then
				resultStr = Str..resultStr
			else
				resultStr = resultStr.."&&"..Str
			end
		end
	
	else
		--结果
		for i=1,#(tmpTable) do
			local Str = tmpTable[i].."="..value
			if(i==#tmpTable) then
				resultStr = Str..resultStr
			else
				resultStr = resultStr..";"..Str
			end
		end
	end
	
	
	return resultStr
end

function anyLen(value)
	g_errorStr = ""
	local resultStr = ""
	local n = g_contextDataTable["CutType"]
	
	--找到所有灯
	local tmpTable = {}
	for i=1,#(g_variableTable) do
		local loadType = g_variableTable[i]["loadType"]
		if  (loadType == "灯") then 
			table.insert(tmpTable,g_variableTable[i]["name"])
		end
	end
	
	local num = CountTable(tmpTable)
	if (num ==0) then
		g_errorStr = "负载类型为灯的变量未找到"
		return resultStr
	end
	
	if(n == 0) then
		--条件
		for i=1,#(tmpTable) do
			local Str = tmpTable[i].."=="..value
			if(i==#tmpTable) then
				resultStr = Str..resultStr
			else
				resultStr = resultStr.."||"..Str
			end
		end
		resultStr = "("..resultStr..")"
	else
		--结果
		g_errorStr = "任意灯亮(灭)术语不能在结果语句中"
	end
	
	
	return resultStr

end

--根据内容在变量数据表找变量key
function variableTableFindTypeAndId(s1)
	 local id = -1
	 g_errorStr = ""
	 for i=1,#(g_variableTable) do
		local name = g_variableTable[i]["name"]
		if(name == s1) then
			id = g_variableTable[i]["id"]
			return id
		end
     end
	 g_errorStr = s1.."在变量表中未找到对应的变量key"
	 return id
end

--在变量数据表找变量名对应的数据类型
function variableTableFindTypeAndName(s1)
	local dataType
	local name
	local num
	 for i=1,#(g_variableTable) do
		name = g_variableTable[i]["name"]
		if  (name == s1) then 
			dataType = g_variableTable[i]["dataType"]
			break
		end
     end
	 return dataType,name
end

--在变量数据表中找所有值描述，只判断是否存在，存在则返回const,不存在返回Identifer
function variableTableFindValueDes(s0,s1)
	local result = "Identifer"
	 for i=1,#(g_variableTable) do
		local name = g_variableTable[i]["name"]
		if( name == s0) then
			--找到s0的变量表
			local valueDesJsonTable = g_variableTable[i]["valueDes"]
				--可能是多个值描述列表
				 for j=1,#(valueDesJsonTable) do
					local valueDesName = valueDesJsonTable[j]["name"]
					if(valueDesName == s1) then
					result = "Const"
					break
				end
			end
		end
     end
	 return result
end

function coverValue(str)
	local resultStr = str
	local n = tonumber(str)
	if n then
	 -- n是数字,就是常量
		resultStr = str
	else
	 -- n转数字失败,就是变量或者字符串
		resultStr = str
	end
	return resultStr
end


function Reverse(name)
	local resultStr = ""
	local id = variableTableFindTypeAndId(name)
	if(id ~= -1) then
		resultStr = "Reverse("..math.modf(id)..")"
	end
	
	
	return resultStr
end



function coverFindDelayName()
   -- 查找延时变量的名称
    local result = "DelayVar";
	return result;
end

function Split(szFullString, szSeparator) 
	local nFindStartIndex = 1 
	local nSplitIndex = 1 
	local nSplitArray = {} 
	while true do 
	  local nFindLastIndex = string.find(szFullString, szSeparator, nFindStartIndex) 
	  if not nFindLastIndex then 
		nSplitArray[nSplitIndex] = string.sub(szFullString, nFindStartIndex, string.len(szFullString)) 
		break 
	  end 
	  nSplitArray[nSplitIndex] = string.sub(szFullString, nFindStartIndex, nFindLastIndex - 1) 
	  nFindStartIndex = nFindLastIndex + string.len(szSeparator) 
	  nSplitIndex = nSplitIndex + 1 
	end 
	return nSplitArray 
end

function DelayFunc(s1,s2,s3)
	local result = ""
	local name = coverFindDelayName();
	
	--对s3进行进一步判断，是否有#：A#B#C
	local spiltTable = Split(s3,"、")
	local count = CountTable(spiltTable)
	
	local i = 1
	local resultS3 = ""
	for k,v in pairs(spiltTable) do 
		--print("k = ",k," v = ",v)
		if( i ~= #spiltTable) then 
			resultS3 =resultS3..v..";"
		else
			resultS3 =resultS3..v
		end
		i = i+1
	end
	--print("resultS3:",resultS3)
	
	--返回一个json格式
	local resultJson = {}
	resultJson[1] = {
		["SrcValue"] = "Delay("..s1..","..math.modf(s2)..")",
		["Type"] = 0
	}
	resultJson[2] = {
		["SrcValue"] = name.."=="..s1.."@"..resultS3,
		["Type"] = 1
	}
	
	result = cjson.encode(resultJson);
	
	
	--result = "Delay("..s1..","..math.modf(s2)..")"..";"..name.."=="..s1.."@"..resultS3
	
	
	
	return result
end



--场景上下切换
function coverAdaptSceneTable(s1,s2)
	g_errorStr = ""
	
	local result = ""
	
	for i=1,#(g_adaptSceneTable) do
		local adaptSceneName = g_adaptSceneTable[i]["adaptSceneName"]
		local adaptSceneRowName  = g_adaptSceneTable[i]["adaptSceneRowName"]
		if  (adaptSceneName == s1) then 
			local adaptSceneNo = g_adaptSceneTable[i]["adaptSceneNo"];
			result = "AdaptSceneTable("..math.modf(adaptSceneNo)..","..s2..")"
			return result
		end
     end
	g_errorStr = "在自适应场景表中未找到("..s1..")的相应数据"
	
	return result
end

--场景名称，左/右切换
function coverSwitch(s1,s2)
	g_errorStr = ""

	local result
	if(#g_deviceTable == 0) then
		g_errorStr = "设备切换表不存在"
		return result
	end
	
	 for i=1,#(g_deviceTable) do
		local deviceName = g_deviceTable[i]["deviceName"]
		if  (deviceName == s1) then 
			local nodeNo = g_deviceTable[i]["nodeNo"];
			local nodeInnerProductNo = g_deviceTable[i]["nodeInnerProductNo"];
			local channelNo = g_deviceTable[i]["channelNo"];
			local hostNo = g_deviceTable[i]["hostNo"];
			result = "Switch("..math.modf(nodeNo)..","..math.modf(nodeInnerProductNo)..","..math.modf(channelNo)..","..math.modf(hostNo)..","..s2..")"
			return result
		end
     end
	g_errorStr = "在设备切换表中未找到设备名("..s1..")的相应数据"
	return result

end


--自适应场景名称，执行自适应场景表行名称
function coverCheckAdaptSceneTable(s1,s2)

	g_errorStr = ""
	local result
	if(#g_adaptSceneTable == 0) then
		g_errorStr = "自适应场景表不存在"
		return result
	end
	
	for i=1,#(g_adaptSceneTable) do
		local adaptSceneName = g_adaptSceneTable[i]["adaptSceneName"]
		local adaptSceneRowName  = g_adaptSceneTable[i]["adaptSceneRowName"]
		if  (adaptSceneName == s1 and adaptSceneRowName == s2 ) then 
			local adaptSceneNo = g_adaptSceneTable[i]["adaptSceneNo"];
			local adaptSceneRowNo = g_adaptSceneTable[i]["adaptSceneRowNo"];
			--print("adaptSceneNo:",adaptSceneNo);
			--print("adaptSceneRowNo:",adaptSceneRowNo);
			result = "vAdaptScene=="..math.modf(adaptSceneNo).."&&CheckAdaptScene("..math.modf(adaptSceneNo)..","..math.modf(adaptSceneRowNo)..")"
			return result
		end
     end
	g_errorStr = "在自适应场景表中未找到("..s1..","..s2..")的相应数据"
	
	return result
end


