local p={}
local lib_arg={}
local lib_str=mw.ustring
local yesno = require('Module:Yesno')
local main_template_name = "變數"
local module_call ="#invoke:Var"
local soft_subst_main = "Softsubst"
local messages,_L,lib_es,lib_tc,command_list = {
	magic_space = '\127'..string.char( 0xC2, 0xA0 ),
	strip_mark = "\127'\"`UNIQ--%s-%s-QINU`\"'\127",
	strip_mark_pattern = "\127'\"`UNIQ%%-%%-%s%%-%s%%-QINU`\"'\127",
	arg_global = '_arg_process',
	cant_subst = '替換引用階段無法存取變數',
	cat_subst_not_done = "未完成替換引用的頁面",
	not_support_strip_warning_cmt = "<!--可能需要手動調整的擴展標籤-->",
	not_support_strip_warning = "[[Template:softsubst]]警告:欲顯示替換引用原碼的模板中包含了擴展標籤,可能導致結果不準確,或替換引用失敗。",
	do_subst = '<p class="notice metadata" id="spoiler" style="font-size: small">以下内容為[[WP:Subst|替換引用]]後的預期內容,請自行拷貝原始碼完成替換引用。</p><div style="clear: both; overflow: auto; border: 1px solid #cccccc; padding: 4px; text-align: left; background: transparency;">',
	remove_hide_strip_mark = "<span%s+style%s*=%s*[\"\']%s*display%s*:%s*none%s*;?%s*[\"\']%s*>[^<]+UNIQ%-%-nowiki[^<]+<%s*/%s*span%s*>",
	var_undefine = '變數 "%s" 未定義。',
	NullPointerException = '[[NullPointerException|空指標]]錯誤'},{p=p},require("Module:EditState"),
	require("Module:TrackingCategory"),{'none',
	set = {'set', '設定', '設置'},
	get = {'get', '取值','取', '取得'},
	getconst = {'getconst'},
	ref = {'ref', '取址'},
	refget = {'refget', 'refgetname'},
	hide = {'hide', '隱藏'},
	subst = {'subst'},
	call = {'call', 'callconst', '呼叫', '執行', '運行'},
	hist = {'hist', '歷史'},
	delete = {'del', 'delete', '刪除'},
	new = {'new'},
};
local notsupport_strip = false
local no_color = false
local printf = lib_str.format
local sub = lib_str.sub
local gsub = lib_str.gsub
local trim = mw.text.trim
local split = mw.text.split
local function _test_cmd(cmd_names, test)
	local result, trim_test = false, trim(lib_str.lower(test))
	for i=1,#cmd_names do result = result or (trim_test == cmd_names[i]) end
	return result
end
local function addWarning(msg)
	return mw.addWarning(require('Module:Error').error{[1] = msg})
end
local function codeNowikiWithColor(frame, code_lang, text)
	if no_color then return frame:extensionTag('nowiki',text) end
	return frame:extensionTag('syntaxhighlight',text, {inline='', lang=code_lang})
end
local strip_code_color_map = {}
local ignore_strip_code = {
	indicator = true, 
	h=true,
	item=true
}
local function strip_code_color(frame, strip_code)
	local strip_type = strip_code:lower()
	if ignore_strip_code[strip_type] == true then return {'',''} end
	if no_color then return {messages.not_support_strip_warning_cmt .. '<' .. strip_type .. '>', '</' .. strip_type .. '>'} end
	local result = strip_code_color_map[strip_type]
	if result then return result else
		strip_code_color_map[strip_type] = {
			codeNowikiWithColor(frame, 'xml', messages.not_support_strip_warning_cmt .. '<' .. strip_type .. '>'),
			codeNowikiWithColor(frame, 'xml', '</' .. strip_type .. '>')
		}
	end
	return strip_code_color_map[strip_type]
end
local function no_color_check(frame, text)
	if no_color then return frame:extensionTag('pre',text) end
	return text
end
local function out_new_line()
	if no_color then return '\n' end
	return tostring(mw.html.create( 'br' ))
end
local subst_pattern = "%s*[Ss][Uu][Bb][Ss][Tt]%s*:%s*"
local safesubst_pattern = "%s*[Ss][Aa][Ff][Ee][Ss][Uu][Bb][Ss][Tt]%s*:%s*"
local msg_pattern = "%s*[Mm][Ss][Gg]%s*:%s*"
local msgnw_pattern = "%s*[Mm][Ss][Gg][Nn][Ww]%s*:%s*"
--區域變數結尾
local _jsonEncode =require('Module:EncoderUtil')._jsonEncode

--函數本體
function p.Varfunc(frame, from_meta_table)
	local args, working_frame = p._arg_process(frame)
	if mw.isSubsting() then return 
		require('Module:Template invocation').invocation(string.format("%s|%s",module_call,'softSubst_msg'), args)
	end
	local command = args['1'] or args[1] or ''
	if _test_cmd(command_list.set, command) or _test_cmd(command_list.new, command) or _test_cmd(command_list.delete, command) then
		local m_mode = 'VAR'
		if _test_cmd(command_list.delete, command) then m_mode = 'DELETE' 
		elseif _test_cmd(command_list.new, command) then m_mode = 'NEW' end
	   	local call_args = {}
	    for key,val in pairs(args) do
	    	local checker = tonumber(key)
	    	if checker ~= 1 then call_args[key] = val end
	    end
	    return p.makeVar(call_args, m_mode, from_meta_table)
	elseif _test_cmd(command_list.get, command) then
	   	return p.getVar({args['2'] or args[2] or '', args['3'] or args[3],default=args.default}, 'value', false ,from_meta_table)
	elseif _test_cmd(command_list.ref, command) then
	   	return p.getVar({args['2'] or args[2] or ''}, 'addr', false ,from_meta_table)
	elseif _test_cmd(command_list.getconst, command) then
	   	return p.getVar({args['2'] or args[2] or ''}, 'value', true, from_meta_table)
	elseif _test_cmd(command_list.refget, command) then
	   	local addr = args['2'] or args[2] or ''
	   	local result = p._getRefVarObj('VAR', addr)
	   	local remappingTable = {refget = 'value', refgetname = 'name'}
	   	if result then
	   		if result[remappingTable[command]] then return result[remappingTable[command]] end
	   	end
	   	return mw.getCurrentFrame():expandTemplate{ title = 'Error', args = { messages.NullPointerException } }
	elseif _test_cmd(command_list.hide, command) then
	   	if trim(args['2'] or args[2] or '')~= '' then
			working_frame:extensionTag('ref', args['2'] or args[2] or '', {group = 'UINQ-VARDEF-BLOCK-QINU'})
			working_frame:extensionTag('references', '', {group = 'UINQ-VARDEF-BLOCK-QINU'})
		end
	   	return ''
	elseif _test_cmd(command_list.subst, command) then
	   	return p._softSubst({args['2'] or args[2] or ''})
	elseif _test_cmd(command_list.call, command) then
	    return p.callVar(p._seek_arg(args, 1), command == 'callconst')
	elseif _test_cmd(command_list.hist, command) then
	    return p.getVarHist(p._seek_arg(args, 1), from_meta_table)
	end
	return ''
end

p.Var={
	set=function(i)local j=p._seek_arg(i,-1,true);for k,l in pairs(i)do j[k]=j[k]or l end j[1]='set';return p.Varfunc(j,true)end,
	new=function(i)local j=p._seek_arg(i,-1,true);for k,l in pairs(i)do j[k]=j[k]or l end j[1]='new';return p.Varfunc(j,true)end,
	delete=function(i)local j=p._seek_arg(i,-1,true);for k,l in pairs(i)do j[k]=j[k]or l end j[1]='delete';return p.Varfunc(j,true)end,
	get=function(i)local j=p._seek_arg(i,-1,true);j[1]='get';return p.Varfunc(j,true)end,
	getconst=function(i)local j=p._seek_arg(i,-1,true);j[1]='getconst';return p.Varfunc(j,true)end,
	hist=function(i)local j=p._seek_arg(i,-1,true);j[1]='hist';return p.Varfunc(j,true)end,
	call=function(i)local j=p._seek_arg(i,-1,true);j[1]='call';return p.Varfunc(j,true)end,
	refget=function(i)local j=p._seek_arg(i,-1,true);j[1]='refget';return p.Varfunc(j,true)end,
	refgetname=function(i)local j=p._seek_arg(i,-1,true);j[1]='refgetname';return p.Varfunc(j,true)end,
	ref=function(i)local j=p._seek_arg(i,-1,true);j[1]='ref';return p.Varfunc(j,true)end,
	vars=function(const)
		local arg_table = p._getVars("VAR", const)
		local restlt = {}
		for key,val in pairs(arg_table) do
			local get_result, check_json = mw.ustring.gsub(arg_table[key].value, "^%$JSON%$", '')
	    	if check_json > 0 then
	    		restlt[key] = mw.text.jsonDecode(get_result)
	    	else
	    		restlt[key] = get_result
	    	end
		end
		return restlt
	end
}

p.Var=setmetatable(p.Var, {
	__index = function(t, k) return t.get({k})end,
	__newindex = function(t, k, v)
		local stored = t.set({[k]=v})
		p.Varfunc({'hide',stored})
	end
})

function p.makeVar(frame, mode, from_meta_table)
	local varMode = mode or 'VAR'
	if varMode == 'NEW' then varMode = 'VAR' end
	if trim(varMode) == '' then varMode = 'VAR' end
	local args, working_frame = p._arg_process(frame)
    local out_text = function(out_mode,name,value)
    	return printf(messages.magic_space .. "$%s_DEF %s=%s" .. messages.magic_space, out_mode, name, value)
    end
    local body = ''
    local new_body = ''
    for key,val in pairs(args) do
    	local store_value = val
    	if from_meta_table == true then 
    		if type(store_value)~=type('string')then store_value="$JSON$".._jsonEncode(store_value)end 
    	end
    	if mode == 'DELETE' then body = body..out_text(varMode,store_value,store_value)..';'
    	else
    		if mode == 'NEW' then new_body = new_body..out_text('DELETE',key,key)..';' end
    		body = body..out_text(varMode,key,store_value)..';' 
    	end
    end
    if mode == 'NEW' then new_body = working_frame:extensionTag('nowiki', new_body) end
    body = new_body .. working_frame:extensionTag('nowiki', body)
	return mw.text.tag( 'span', {style="display:none;"}, body )
end

function p.softSubst(frame)
	local args, working_frame = p._arg_process(frame)
	if mw.isSubsting() then return require('Module:Template invocation').invocation(soft_subst_main, args)end
	local template_title = trim(args['1'] or args['1'] or '')
	if template_title == '' then return '' end
	return p.softSubst_msg(p._seek_arg(args, 1), template_title,
		yesno(args['no cat']or args['no_cat']or args.nocat or args.NoCat or args.noCat or false))
end
local function check_is_main_doc(working_frame)
	local checker = mw.ustring.lower(working_frame:preprocess( "{{BASEPAGENAME}}" ))
	if	checker == mw.ustring.lower(main_template_name) or 
		checker == mw.ustring.lower(soft_subst_main) or checker == 'var' then return true end
    return false
end
function p.softSubst_msg(frame, template_title, without_cat)
	local template_dis = template_title or main_template_name
	local args, working_frame = p._arg_process(frame)
	if mw.isSubsting() then return require('Module:Template invocation').invocation(string.format("%s|%s",module_call,'softSubst_msg'), args)end
	local result = require('Module:Template invocation').invocation(template_dis, args)
	if lib_es.isPreview() then 
		local pre_result  = working_frame:preprocess(result)
		if #(split(gsub(pre_result,'\r\n','\n'),'\n')) > 50 then no_color = true end
		result = p._softSubst({working_frame:preprocess(result)})
		if template_title == nil then 
			result = working_frame:expandTemplate{ title = 'Error', args = { messages.cant_subst } } .. result
		end
		if notsupport_strip==true then result = '<p>{{Error|' .. messages.not_support_strip_warning .. '}}</p>' .. result end
	else
		if (check_is_main_doc(working_frame) == false) and (not without_cat) then lib_tc.append(messages.cat_subst_not_done) end
	end
	if notsupport_strip==true then addWarning( messages.not_support_strip_warning ) end
	return working_frame:preprocess(result)
end

function p._softSubst(frame)
	local softSubst_data, softSubst_warp = 'arg_global', string.char(0x70)
	if type(softSubst_data) ~= type({'table'}) then
		--find method between global scope or local scope
		softSubst_data = {(_G[softSubst_warp] or _L[softSubst_warp])[messages[softSubst_data]](frame)}
	end
	local without_cat = yesno(softSubst_data['no cat']or softSubst_data['no_cat']or softSubst_data['nocat']or softSubst_data['NoCat']or softSubst_data['noCat']or false)
	--decode method
	local first_data, second_data, third_data = softSubst_data['1'] or softSubst_data[1], softSubst_data['2'] or softSubst_data[2], (_G[softSubst_warp] or _L[softSubst_warp])["_code_getter_wiki"]
	--2nd layer decode
	first_data = first_data['1'] or first_data[1] or ''
	--second_data = second_data['2'] or second_data[2] or ''
	--third_data = third_data['3'] or third_data[3] or ''
	if lib_es.isPreview() ~= true and (not without_cat) then 
		if (check_is_main_doc(second_data) == false) then lib_tc.append(messages.cat_subst_not_done) end
	end
	local fourth_data = function(msg_data)
		local msg_data_list, result_code = split(msg_data, '\n'), ''
		for i=1,#msg_data_list do result_code = result_code .. third_data(second_data, msg_data_list[i]) end
		if no_color then result_code = no_color_check(second_data, result_code) end
		return result_code
	end
	--foreach method do
   	if trim(first_data)~= '' then return
   		mw.clone(messages.do_subst) .. fourth_data(gsub(
			gsub(first_data, messages.remove_hide_strip_mark, '')
		, '\r\n', '\n')) .. '</div>'
	end
   	return ''
end

function p.callVar(frame, const)
	local args, working_frame = p._arg_process(frame)
    local vars = p._getVars('VAR', const)
    local var_name = args[1]or args['1']or''
    local get_value = vars[var_name]
    if tonumber(var_name) and not get_value then get_value = vars[tonumber(var_name)] end
    if get_value then 
    	local func_name = trim(mw.clone(get_value.value),"|\t\r\n\f ")
    	func_name = gsub(func_name,subst_pattern,'')
    	func_name = gsub(func_name,safesubst_pattern,'')
    	func_name = gsub(func_name,msg_pattern,'')
    	func_name = gsub(func_name,msgnw_pattern,'')
    	
    	local tail_index = (lib_str.find(func_name,'|')or(lib_str.len(func_name)+1))-1
    	command_tail = sub(func_name,tail_index + 1,-1)
    	func_name = sub(func_name,1,tail_index)

    	local final_func_name = ''
    	
		--template:
		local template_name = mw.title.new( func_name, 'Template' )
		if template_name and template_name.exists then 
			final_func_name = template_name.fullText 
			if template_name.namespace == 0 then final_func_name = ':' .. final_func_name end
		end 

		--int:
		local template_split = split(func_name, ':') or {func_name}
		if final_func_name=='' then
			local check_mw = func_name
			if #template_split > 1 and (sub(template_split[1],1,3) == 'int' or 
					(lib_str.find(template_split[1],"[Mm]edia[Ww]iki"))) then
				check_mw = table.concat( template_split, ':', 2, #template_split )
			end
			if mw.message.new(check_mw):exists() then
				final_func_name = 'int:' .. check_mw
			end
		end

		--#...:
		local fix_cs = false
		if final_func_name=='' then
			if xpcall(function()mw.getCurrentFrame():callParserFunction( func_name, func_name )end, function()end) 
					== true then
				final_func_name = func_name
				fix_cs = true
				local parser_tail_check = sub(trim(final_func_name),-1)
				if parser_tail_check ~= ':' and parser_tail_check ~= '|' then final_func_name = final_func_name .. ':' end
			end
		end

		--may be magic word
		if final_func_name=='' then
			local checker, check_text = xpcall(function()
				return mw.getCurrentFrame():preprocess( printf("{{%s}}", func_name) )
			end, function()end)
			local test_name = (template_name or { prefixedText = func_name }).prefixedText
			if		not lib_str.find(check_text or '', printf("^{{%s}}$", test_name) ) and
					not lib_str.find(check_text or '', printf("^%%[%%[:%s%%]%%]$", test_name) ) then
				final_func_name = func_name
			end
		end

		if trim(final_func_name) ~= '' then
		    local num_args = p._seek_arg(args, 1)

			local str_args = require('Module:Template invocation').invocation(final_func_name..command_tail, num_args)
			if fix_cs == true and trim(command_tail) == '' and 
					sub(trim(final_func_name),-1) == ':' then 
				str_args = gsub(str_args, "^({{)%s*(" .. final_func_name .. ")|", "%1%2")
			end
			return working_frame:preprocess(str_args)
		end
		local max_arg = 0 
    	local num_args = {}
		for key,value in pairs( args ) do
			local arg_id = tonumber(key or '')
			if arg_id then
				if arg_id > max_arg then max_arg = arg_id end
				num_args[arg_id] = value
			end
		end
		local call_args = {}
		local get_obj = function(obj)return mw.text.jsonDecode(obj)end
		if max_arg > 1 then
			for i = 2,max_arg do
				if num_args[i] then 
					local try_to_get_obj = mw.clone(num_args[i])
					if not xpcall( function() --try
						try_to_get_obj = get_obj(num_args[i])
					end, function(msg)return msg end ) then --catch
						call_args[i-1] = num_args[i]
					else --finally
						call_args[i-1] = try_to_get_obj
					end
				else call_args[i-1] = '' end
			end
		end
		local func_path = split(func_name,'%.') or { [1]=func_name }
		local func_body = mw[func_path[1]] or p[func_path[1]] or _G[func_path[1]]
		if lib_str.find(func_path[1],':') then
			func_body = require(func_path[1]) or func_body
		end
		if func_body then
			local old_obj = func_body
			for i=2,#func_path do
				func_body = func_body[func_path[i]]
				if func_body then
					old_obj = func_body
				else
					return ''
				end
			end
			local func_type = type( func_body )
			local times = 10
			for ti = 1,times do
				if func_type == type(nil) then
					return ''
				elseif func_type == type(0) then
					return '' .. func_body
				elseif func_type == type(true) then
					if func_body then return '1' end
					return ''
				elseif func_type == type(type) then
					if max_arg > 1 then 
						func_body = func_body(unpack(call_args))
						if func_body == nil then func_body = call_args[1] end
					else func_body = func_body() end
				elseif func_type == type("string") then
					return func_body
				elseif func_type == type({}) then
					return _jsonEncode(func_body)
				end
				func_type = type( func_body )
			end
		end
		return func_name
    end
    if trim(var_name) ~= '' then
    	return working_frame:expandTemplate{ title = 'Error', args = { printf(messages.var_undefine, var_name) } }
    end
	return ''
end
function p._arg_process(frame)
	local args, working_frame
    if frame == mw.getCurrentFrame() then
        -- We're being called via #invoke. The args are passed through to the module
        -- from the template page, so use the args that were passed into the template.
        if lib_arg.getArgs == nil then lib_arg = require('Module:Arguments') end
        args = lib_arg.getArgs(frame, {
        	parentFirst=true,
        	trim = false,
			removeBlanks = false
        })
        working_frame = frame
    else
        -- We're being called from another module or from the debug console, so assume
        -- the args are passed in directly.
        args = frame
        working_frame = mw.getCurrentFrame()
        if type(args) ~= type({}) then args = {frame} end
    end
    return args, working_frame
end
function p.getVar(frame, get_mode, const, from_meta_table)
	local to_get_mode = get_mode or 'value'
	local args, working_frame = p._arg_process(frame)
	local vars = p._getVars('VAR', const)
    local var_name = args[1]or args['1']or''
    local get_value = vars[var_name]
    if tonumber(var_name) and not get_value then get_value = vars[tonumber(var_name)] end
    if get_value then 
    	local get_result, check_json = mw.ustring.gsub(get_value[to_get_mode], "^%$JSON%$", '')
    	if check_json > 0 and from_meta_table == true then
    		return mw.text.jsonDecode(get_result)
    	end
    	return get_result
    end
    if trim(var_name) ~= '' then
    	if args[2]or args['2'] or args.default then return args[2]or args['2']or args.default end
    	if from_meta_table == true then return error(printf(messages.var_undefine, var_name)) end
    	return working_frame:expandTemplate{ title = 'Error', args = { printf(messages.var_undefine, var_name) } }
    end
	return ''
end

function p.getVarHist(frame, from_meta_table)
	local args, working_frame = p._arg_process(frame)
    local vars = p._getVars('VAR') 
    local var_name = args[1]or args['1']or''
    local get_value = vars[var_name]
    if tonumber(var_name) and not get_value then get_value = vars[tonumber(var_name)] end
    if get_value then 
    	local formats = args[2]or args['2']or'$'
    	local seps = args[3]or args['3']or', '
    	local hists = split(get_value.hist,'$\127;\127^')
    	local body = ''
    	if from_meta_table == true then 
    		local get_result, check_json = {}, -1
    		for i=1,#hists do
    			get_result[i], check_json = mw.ustring.gsub(hists[i], "^%$JSON%$", '')
		    	if check_json > 0 then
		    		get_result[i] = mw.text.jsonDecode(get_result[i])
		    	end
    		end
    		return get_result 
    	end
    	for i=1,#hists do
    		if i>1 then body = body .. seps end
    		body = body .. gsub(formats, '%$', hists[i])
    	end
    	return body
    end
    if trim(var_name) ~= '' then
    	if from_meta_table == true then return error(printf(messages.var_undefine, var_name)) end
    	return working_frame:expandTemplate{ title = 'Error', args = { printf(messages.var_undefine, var_name) } }
    end
	return ''
end

function p._getRefVarObj(VarMode, addr)
	local addr_path = split(addr,':')
	if #addr_path == 2 then
		local strip_id, addr_loc = addr_path[1], addr_path[2]
		strip_id = tonumber(strip_id)
		addr_loc = tonumber(addr_loc)
		if strip_id and addr_loc then
			local try_get = mw.text.unstripNoWiki( p._stripMark('nowiki', string.format( "%08X", strip_id )) )
			local in_index, arg_data = 1, nil
			gsub(try_get, messages.magic_space .. "%$" .. VarMode .. "_DEF%s+([^=]+)=([^" .. messages.magic_space .. ']*)', 
			function(f_key, f_value)
				local key, value = f_key, f_value
				key = trim(key)
				if in_index == addr_loc then 
					arg_data = {
						name=key,
						value=value,
						addr=string.format( "%d:%d", strip_id, in_index )
					} end
				in_index = in_index + 1
			end)
			return arg_data
		end
	end
	return nil
end
function p._seek_arg(input_args_list, offset, enable_minus)
    local num_args = {}
    if enable_minus~=true and offset <= 1 then offset = 1 end
	for key,value in pairs(input_args_list) do
		local num = tonumber(key) or 0
		local stored = false
		if num then
			if num > offset then
				num_args[num - offset] = value
				stored = true
			end
			if num >= 1 and num <= offset then stored = true end
		end
		if stored ~= true then num_args[key] = value end
	end
	return num_args
end
function p._code_getter_wiki(working_frame, input_code)
	local current_text, code_lang = input_code, "moin"
	local flag1 = lib_str.find(current_text, "<%s*/?%s*[A-Za-z]")
	local flag2 = lib_str.find(current_text, "[A-Za-z\"']%s*/?%s*>")
	if flag1 or flag2 then code_lang = "html" end
	local body = ''
	local strip_to_remove = split(current_text,'\127')
	for i=1,#strip_to_remove do
		local current_strip = strip_to_remove[i]
		if lib_str.find(current_strip,"'\"`UNIQ%-%-") then
			if lib_str.find(current_strip, "nowiki") then 
				local try_unstrip = '\127' .. current_strip .. '\127'
				try_unstrip = mw.text.unstripNoWiki( try_unstrip )
				if lib_str.find(try_unstrip,"'\"`UNIQ%-%-") then
					--不存在的strip entity
					body = body .. '\127' .. current_strip .. '\127'
				else
					try_unstrip = mw.text.decode(try_unstrip)
					try_unstrip = printf("<nowiki>%s</nowiki>",table.concat( split(try_unstrip,"nowiki"),'</nowiki>nowiki<nowiki>'))
					body = body .. codeNowikiWithColor(working_frame, 'xml', try_unstrip)
				end
			else
				--保留原始strip符號令解析器自動替換
				local strip_type = ''
				gsub(current_strip, "UNIQ%-%-([%dA-Za-z]+)%-", function(in_str)strip_type=in_str end)
				local out_strip_text = '\127' .. current_strip .. '\127'
				if strip_type ~= '' then 
					local strip_code_color_data = strip_code_color(working_frame, strip_type)
					out_strip_text = strip_code_color_data[1] .. out_strip_text ..strip_code_color_data[2]
				end
				body = body .. out_strip_text
				notsupport_strip = true
			end
		elseif trim(current_strip) ~= '' then
			local avoid_t = split(current_strip, '%-{') or {avoid_t}
			for a_i = 1,#avoid_t do
				local a_ic = avoid_t[a_i]
				if a_i ~= 1 then a_ic = '{' .. a_ic end
				if a_i ~= #avoid_t then a_ic = a_ic .. '-' end
				body = body .. codeNowikiWithColor(working_frame, code_lang, a_ic)
			end
		end
	end
	return body .. out_new_line()
end

function p._getVars(VarMode, const)
	local frame = mw.getCurrentFrame()
    local mark_get_mark, max_id = frame:extensionTag( 'nowiki', 'nowiki' ), ''
	gsub(mark_get_mark, 'nowiki%-([0-9A-Za-z]+)%-', function(id)max_id = id end)
	local max_id_num, body = tonumber(max_id, 16), ''
	local symbol_table = {}
	for i=1,max_id_num do
		local try_get = mw.text.unstripNoWiki( p._stripMark('nowiki', string.format( "%08X", i-1 )) )
		local in_index = 1
		gsub(try_get, messages.magic_space .. "%$([A-Z]+)_DEF%s+([^=]+)=([^" .. messages.magic_space .. ']*)', 
		function(sub_mode, f_key, f_value)--VarMode
			local key, value = f_key, f_value
			key = trim(key)
			if key ~= '' then
				local it if const == true then it = symbol_table[key] end
				local old = symbol_table[key]
				if sub_mode == 'DELETE' then symbol_table[key] = nil
				elseif sub_mode == VarMode then
				symbol_table[key] = it or {
					name=key,
					value=value,
					hist=((old or {}).hist and ( (old or {}).hist .. '$\127;\127^' ) or '') .. value,
					addr=string.format( "%d:%d", (i-1), in_index )
				}end
			end
			in_index = in_index + 1
		end)
	end
	return symbol_table
end
function p._stripMark(mark_name, mark_id)
	return printf(messages.strip_mark, mark_name, mark_id)
end
return p