#if USE_UNI_LUA
using LuaAPI = UniLua.Lua;
using RealStatePtr = UniLua.ILuaState;
using LuaCSFunction = UniLua.CSharpFunctionDelegate;
#else
using LuaAPI = XLua.LuaDLL.Lua;
using RealStatePtr = System.IntPtr;
using LuaCSFunction = XLua.LuaDLL.lua_CSFunction;
#endif

using XLua;
using System.Collections.Generic;
<%ForEachCsList(namespaces, function(namespace)%>using <%=namespace%>;<%end)%>
<%
require "TemplateCommon"

local OpNameMap = {
    op_Addition = "__AddMeta",
	op_Subtraction = "__SubMeta",
	op_Multiply = "__MulMeta",
	op_Division = "__DivMeta",
	op_Equality = "__EqMeta",
	op_UnaryNegation = "__UnmMeta",
	op_LessThan = "__LTMeta",
	op_LessThanOrEqual = "__LEMeta",
	op_Modulus = "__ModMeta",
    op_BitwiseAnd = "__BandMeta",
    op_BitwiseOr = "__BorMeta",
    op_ExclusiveOr = "__BxorMeta",
    op_OnesComplement = "__BnotMeta",
    op_LeftShift = "__ShlMeta",
    op_RightShift = "__ShrMeta",
}

local OpCallNameMap = {
    op_Addition = "+",
	op_Subtraction = "-",
	op_Multiply = "*",
	op_Division = "/",
	op_Equality = "==",
	op_UnaryNegation = "-",
	op_LessThan = "<",
	op_LessThanOrEqual = "<=",
	op_Modulus = "%",
	op_BitwiseAnd = "&",
    op_BitwiseOr = "|",
    op_ExclusiveOr = "^",
    op_OnesComplement = "~",
    op_LeftShift = "<<",
    op_RightShift = ">>",
}

local obj_method_count = 0
local obj_getter_count = 0
local obj_setter_count = 0
local meta_func_count = operators.Count
local cls_field_count = 1
local cls_getter_count = 0
local cls_setter_count = 0

ForEachCsList(methods, function(method)
    if method.IsStatic then
	    cls_field_count = cls_field_count + 1
	else
	    obj_method_count = obj_method_count + 1
    end 
end)

ForEachCsList(events, function(event)
    if event.IsStatic then
	    cls_field_count = cls_field_count + 1
	else
	    obj_method_count = obj_method_count + 1
    end 
end)

ForEachCsList(getters, function(getter)
    if getter.IsStatic then
	    if getter.ReadOnly then
	        cls_field_count = cls_field_count + 1
	    else
		    cls_getter_count = cls_getter_count + 1
		end
	else
	    obj_getter_count = obj_getter_count + 1
    end 
end)

ForEachCsList(setters, function(setter)
    if setter.IsStatic then
	    cls_setter_count = cls_setter_count + 1
	else
	    obj_setter_count = obj_setter_count + 1
    end 
end)

ForEachCsList(lazymembers, function(lazymember)
    if lazymember.IsStatic == 'true' then
	    if 'CLS_IDX' == lazymember.Index then
		    cls_field_count = cls_field_count + 1
	    elseif 'CLS_GETTER_IDX' == lazymember.Index then
		    cls_getter_count = cls_getter_count + 1
		elseif 'CLS_SETTER_IDX' == lazymember.Index then
		    cls_setter_count = cls_setter_count + 1
		end
	else
		if 'METHOD_IDX' == lazymember.Index then
		    obj_method_count = obj_method_count + 1
	    elseif 'GETTER_IDX' == lazymember.Index then
		    obj_getter_count = obj_getter_count + 1
		elseif 'SETTER_IDX' == lazymember.Index then
		    obj_setter_count = obj_setter_count + 1
		end
	end
end)

local v_type_name = CSVariableName(type)
local generic_arg_list, type_constraints = GenericArgumentList(type)

%>
namespace XLua
{
    public partial class ObjectTranslator
    {
        public void __Register<%=v_type_name%><%=generic_arg_list%>(RealStatePtr L) <%=type_constraints%>
        {
		    System.Type type = typeof(<%=CsFullTypeName(type)%>);
			Utils.BeginObjectRegister(type, L, this, <%=meta_func_count%>, <%=obj_method_count%>, <%=obj_getter_count%>, <%=obj_setter_count%>);
			<%ForEachCsList(operators, function(operator)%>Utils.RegisterFunc(L, Utils.OBJ_META_IDX, "<%=(OpNameMap[operator.Name]):gsub('Meta', ''):lower()%>", <%=v_type_name%><%=OpNameMap[operator.Name]%><%=generic_arg_list%>);
            <%end)%>
			<%ForEachCsList(methods, function(method) if not method.IsStatic then %>Utils.RegisterFunc(L, Utils.METHOD_IDX, "<%=method.Name%>", <%=v_type_name%>_m_<%=method.Name%><%=generic_arg_list%>);
			<% end end)%>
			<%ForEachCsList(events, function(event) if not event.IsStatic then %>Utils.RegisterFunc(L, Utils.METHOD_IDX, "<%=event.Name%>", <%=v_type_name%>_e_<%=event.Name%><%=generic_arg_list%>);
			<% end end)%>
			<%ForEachCsList(getters, function(getter) if not getter.IsStatic then %>Utils.RegisterFunc(L, Utils.GETTER_IDX, "<%=getter.Name%>", <%=v_type_name%>_g_get_<%=getter.Name%><%=generic_arg_list%>);
            <%end end)%>
			<%ForEachCsList(setters, function(setter) if not setter.IsStatic then %>Utils.RegisterFunc(L, Utils.SETTER_IDX, "<%=setter.Name%>", <%=v_type_name%>_s_set_<%=setter.Name%><%=generic_arg_list%>);
            <%end end)%>
			<%ForEachCsList(lazymembers, function(lazymember) if lazymember.IsStatic == 'false' then %>Utils.RegisterLazyFunc(L, Utils.<%=lazymember.Index%>, "<%=lazymember.Name%>", type, <%=lazymember.MemberType%>, <%=lazymember.IsStatic%>);
            <%end end)%>
			Utils.EndObjectRegister(type, L, this, <% if type.IsArray or ((indexers.Count or 0) > 0) then %>__CSIndexer<%=v_type_name%><%=generic_arg_list%><%else%>null<%end%>, <%if type.IsArray or ((newindexers.Count or 0) > 0) then%>__NewIndexer<%=v_type_name%><%=generic_arg_list%><%else%>null<%end%>,
			    null, null, null);

		    Utils.BeginClassRegister(type, L, __CreateInstance<%=v_type_name%><%=generic_arg_list%>, <%=cls_field_count%>, <%=cls_getter_count%>, <%=cls_setter_count%>);
			<%ForEachCsList(methods, function(method) if method.IsStatic then %>Utils.RegisterFunc(L, Utils.CLS_IDX, "<%=method.Overloads[0].Name%>", <%=v_type_name%>_m_<%=method.Name%><%=generic_arg_list%>);
            <% end end)%>
			<%ForEachCsList(events, function(event) if event.IsStatic then %>Utils.RegisterFunc(L, Utils.CLS_IDX, "<%=event.Name%>", <%=v_type_name%>_e_<%=event.Name%><%=generic_arg_list%>);
			<% end end)%>
            <%ForEachCsList(getters, function(getter) if getter.IsStatic and getter.ReadOnly then %>Utils.RegisterObject(L, this, Utils.CLS_IDX, "<%=getter.Name%>", <%=CsFullTypeName(type).."."..getter.Name%>);
            <%end end)%>
			<%ForEachCsList(getters, function(getter) if getter.IsStatic and (not getter.ReadOnly) then %>Utils.RegisterFunc(L, Utils.CLS_GETTER_IDX, "<%=getter.Name%>", <%=v_type_name%>_g_get_<%=getter.Name%><%=generic_arg_list%>);
            <%end end)%>
			<%ForEachCsList(setters, function(setter) if setter.IsStatic then %>Utils.RegisterFunc(L, Utils.CLS_SETTER_IDX, "<%=setter.Name%>", <%=v_type_name%>_s_set_<%=setter.Name%><%=generic_arg_list%>);
            <%end end)%>
			<%ForEachCsList(lazymembers, function(lazymember) if lazymember.IsStatic == 'true' then %>Utils.RegisterLazyFunc(L, Utils.<%=lazymember.Index%>, "<%=lazymember.Name%>", type, <%=lazymember.MemberType%>, <%=lazymember.IsStatic%>);
            <%end end)%>
			Utils.EndClassRegister(type, L, this);
        }
        
        int __CreateInstance<%=v_type_name%><%=generic_arg_list%>(RealStatePtr L, int __gen_param_count) <%=type_constraints%>
        {
            <% 
            if constructors.Count == 0 and (not type.IsValueType)  then 
            %>return LuaAPI.luaL_error(L, "<%=CsFullTypeName(type)%> does not have a constructor!");<% 
            else %>
            ObjectTranslator translator = this;
			<% 
			local hasZeroParamsCtor = false
			ForEachCsList(constructors, function(constructor, ci)
				local parameters = constructor:GetParameters()
				if parameters.Length == 0 then
					hasZeroParamsCtor = true
				end
				local def_count = constructor_def_vals[ci]
				local param_count = parameters.Length
				local in_num = CalcCsList(parameters, function(p) return p.IsIn or not p.IsOut end)
				local out_num = CalcCsList(parameters, function(p) return p.IsOut or p.ParameterType.IsByRef end)
				local real_param_count = param_count - def_count
				local has_v_params = param_count > 0 and IsParams(parameters[param_count - 1])
				local in_pos = 0
			%>if(__gen_param_count <%=has_v_params and ">=" or "=="%> <%=in_num + 1 - def_count - (has_v_params and 1 or 0)%><%ForEachCsList(parameters, function(parameter, pi) 
			if pi >= real_param_count then return end 
			local parameterType = parameter.ParameterType
			if has_v_params and pi == param_count - 1 then  parameterType = parameterType:GetElementType() end
			if parameter.IsIn or not parameter.IsOut then in_pos = in_pos + 1
			%> && <%=GetCheckStatement(parameterType, in_pos+1, has_v_params and pi == param_count - 1)%><% 
			end
			end)%>)
			{
				<%ForEachCsList(parameters, function(parameter, pi) 
				if pi >= real_param_count then return end 
				%><%=GetCasterStatement(parameter.ParameterType, pi+2, parameter.Name, true, has_v_params and pi == param_count - 1)%>;
				<%end)%>
				<%=CsFullTypeName(type)%> __cl_gen_ret = new <%=CsFullTypeName(type)%>(<%ForEachCsList(parameters, function(parameter, pi) if pi >= real_param_count then return end; if pi ~=0 then %><%=', '%><% end ;if parameter.IsOut and parameter.ParameterType.IsByRef then %>out <% elseif parameter.ParameterType.IsByRef then %>ref <% end %><%=parameter.Name%><% end)%>);
				<%=GetPushStatement(type, "__cl_gen_ret")%>;
				<%local in_pos = 0
				ForEachCsList(parameters, function(parameter, pi)
					if pi >= real_param_count then return end
					if parameter.IsIn or not parameter.IsOut then 
						in_pos = in_pos + 1
					end
					if parameter.ParameterType.IsByRef then
					%><%=GetPushStatement(parameter.ParameterType:GetElementType(), parameter.Name)%>;
					<%if not parameter.IsOut and parameter.ParameterType.IsByRef and NeedUpdate(parameter.ParameterType) then 
			  %><%=GetUpdateStatement(parameter.ParameterType:GetElementType(), in_pos+1, parameter.Name)%>;
					<%end%>
				<%
					end
				end)
				%>
				return <%=out_num + 1%>;
			}
			<%end)
			if (not hasZeroParamsCtor) and type.IsValueType then
			%>
			if (__gen_param_count == 1)
			{
				<%=GetPushStatement(type, "default(" .. CsFullTypeName(type).. ")")%>;
				return 1;
			}
			<%end%>
			
            return LuaAPI.luaL_error(L, "invalid arguments to <%=CsFullTypeName(type)%> constructor!");
            <% end %>
        }
        
		<% if type.IsArray or ((indexers.Count or 0) > 0) then %>
        int __CSIndexer<%=v_type_name%><%=generic_arg_list%>(RealStatePtr L, int __gen_param_count) <%=type_constraints%>
        {
			<%if type.IsArray then %>
			ObjectTranslator translator = this;
			if (<%=GetCheckStatement(type, 1)%> && LuaAPI.lua_isnumber(L, 2))
			{
				int index = (int)LuaAPI.lua_tonumber(L, 2);
				<%=GetSelfStatement(type)%>;
				LuaAPI.lua_pushboolean(L, true);
				<%=GetPushStatement(type:GetElementType(), "__cl_gen_to_be_invoked[index]")%>;
				return 2;
			}
			<%elseif indexers.Count > 0 then
			%>ObjectTranslator translator = this;
			<%
				ForEachCsList(indexers, function(indexer)
					local paramter = indexer:GetParameters()[0]
			%>
			if (<%=GetCheckStatement(type, 1)%> && <%=GetCheckStatement(paramter.ParameterType, 2)%>)
			{
				
				<%=GetSelfStatement(type)%>;
				<%=GetCasterStatement(paramter.ParameterType, 2, "index", true)%>;
				LuaAPI.lua_pushboolean(L, true);
				<%=GetPushStatement(indexer.ReturnType, "__cl_gen_to_be_invoked[index]")%>;
				return 2;
			}
			<%end)
			end%>
            LuaAPI.lua_pushboolean(L, false);
			return 1;
        }
		<% end %>
        
		<%if type.IsArray or ((newindexers.Count or 0) > 0) then%>
        int __NewIndexer<%=v_type_name%><%=generic_arg_list%>(RealStatePtr L, int __gen_param_count) <%=type_constraints%>
        {
			<%if type.IsArray or newindexers.Count > 0 then %>ObjectTranslator translator = this;<%end%>
			<%if type.IsArray then 
				local elementType = type:GetElementType()
			%>
			if (<%=GetCheckStatement(type, 1)%> && LuaAPI.lua_isnumber(L, 2) && <%=GetCheckStatement(elementType, 3)%>)
			{
				int index = (int)LuaAPI.lua_tonumber(L, 2);
				<%=GetSelfStatement(type)%>;
				<%=GetCasterStatement(elementType, 3, "__cl_gen_to_be_invoked[index]")%>;
				LuaAPI.lua_pushboolean(L, true);
				return 1;
			}
			<%elseif newindexers.Count > 0 then%>
			<%ForEachCsList(newindexers, function(newindexer)
					local keyType = newindexer:GetParameters()[0].ParameterType
					local valueType = newindexer:GetParameters()[1].ParameterType
			%>
			if (<%=GetCheckStatement(type, 1)%> && <%=GetCheckStatement(keyType, 2)%> && <%=GetCheckStatement(valueType, 3)%>)
			{
				
				<%=GetSelfStatement(type)%>;
				<%=GetCasterStatement(keyType, 2, "key", true)%>;
				<%if IsStruct(valueType) then%><%=GetCasterStatement(valueType, 3, "__cl_gen_value", true)%>;
				__cl_gen_to_be_invoked[key] = __cl_gen_value;<%else
			  %><%=GetCasterStatement(valueType, 3, "__cl_gen_to_be_invoked[key]")%>;<%end%>
				LuaAPI.lua_pushboolean(L, true);
				return 1;
			}
			<%end)
			end%>
			LuaAPI.lua_pushboolean(L, false);
            return 1;
        }
		<% end %>
        
        <%ForEachCsList(operators, function(operator) %>
        int <%=v_type_name%><%=OpNameMap[operator.Name]%><%=generic_arg_list%>(RealStatePtr L, int __gen_param_count) <%=type_constraints%>
        {
            ObjectTranslator translator = this;
            <% if operator.Name ~= "op_UnaryNegation" and operator.Name ~= "op_OnesComplement"  then 
                ForEachCsList(operator.Overloads, function(overload)
                local left_param = overload:GetParameters()[0]
                local right_param = overload:GetParameters()[1]
            %>
			if (<%=GetCheckStatement(left_param.ParameterType, 1)%> && <%=GetCheckStatement(right_param.ParameterType, 2)%>)
			{
				<%=GetCasterStatement(left_param.ParameterType, 1, "leftside", true)%>;
				<%=GetCasterStatement(right_param.ParameterType, 2, "rightside", true)%>;
				
				<%=GetPushStatement(overload.ReturnType, "leftside " .. OpCallNameMap[operator.Name] .. " rightside")%>;
				
				return 1;
			}
            <%end)%>
            return LuaAPI.luaL_error(L, "invalid arguments to right hand of <%=OpCallNameMap[operator.Name]%> operator, need <%=CsFullTypeName(type)%>!");
            <%else%>
			<%=GetCasterStatement(type, 1, "rightside", true)%>;
			<%=GetPushStatement(operator.Overloads[0].ReturnType, OpCallNameMap[operator.Name] .. " rightside")%>;
            return 1;
            <%end%>
        }
        <%end)%>
        
        <%ForEachCsList(methods, function(method)%>
        int <%=v_type_name%>_m_<%=method.Name%><%=generic_arg_list%>(RealStatePtr L, int __gen_param_count) <%=type_constraints%>
        {
            <%
            local need_obj = not method.IsStatic
            if MethodCallNeedTranslator(method) then
            %>
            ObjectTranslator translator = this;
            <%end%>
            <%if need_obj then%>
            <%=GetSelfStatement(type)%>;
            <%end%>
			<%ForEachCsList(method.Overloads, function(overload, oi)
			local parameters = MethodParameters(overload)
			local in_num = CalcCsList(parameters, function(p) return p.IsIn or not p.IsOut end)
			local param_offset = method.IsStatic and 0 or 1
			local out_num = CalcCsList(parameters, function(p) return p.IsOut or p.ParameterType.IsByRef end)
			local in_pos = 0
			local has_return = (overload.ReturnType.FullName ~= "System.Void")
			local def_count = method.DefaultValues[oi]
			local param_count = parameters.Length
			local real_param_count = param_count - def_count
			local has_v_params = param_count > 0 and IsParams(parameters[param_count - 1])
			if method.Overloads.Count > 1 then
			%>if(__gen_param_count <%=has_v_params and ">=" or "=="%> <%=in_num+param_offset-def_count - (has_v_params and 1 or 0)%><%
				ForEachCsList(parameters, function(parameter, pi)
					if pi >= real_param_count then return end
					local parameterType = parameter.ParameterType
					if has_v_params and pi == param_count - 1 then  parameterType = parameterType:GetElementType() end
					if parameter.IsIn or not parameter.IsOut then in_pos = in_pos + 1; 
					%>&& <%=GetCheckStatement(parameterType , in_pos+param_offset, has_v_params and pi == param_count - 1)%><% 
					end 
				end)%>) <%end%>
			{
				<% 
				in_pos = 0;
				ForEachCsList(parameters, function(parameter, pi) 
					if pi >= real_param_count then return end
					%><%if parameter.IsIn or not parameter.IsOut then 
						in_pos = in_pos + 1
					%><%=GetCasterStatement(parameter.ParameterType, in_pos+param_offset, parameter.Name, true, has_v_params and pi == param_count - 1)%><%
					else%><%=CsFullTypeName(parameter.ParameterType)%> <%=parameter.Name%><%end%>;
				<%end)%>
				<%
				if has_return then
				%><%=CsFullTypeName(overload.ReturnType)%> __cl_gen_ret = <%
				end
				%><%if method.IsStatic then
				%><%=CsFullTypeName(type).."."..UnK(overload.Name)%><%
				else
				%>__cl_gen_to_be_invoked.<%=UnK(overload.Name)%><%
				end%>( <%ForEachCsList(parameters, function(parameter, pi) 
					if pi >= real_param_count then return end
					if pi ~= 0 then %>, <% end; if parameter.IsOut and parameter.ParameterType.IsByRef then %>out <% elseif parameter.ParameterType.IsByRef then %>ref <% end %><%=parameter.Name%><% end) %> );
				<%
				if has_return then
				%><%=GetPushStatement(overload.ReturnType, "__cl_gen_ret")%>;
				<%
				end
				local in_pos = 0
				ForEachCsList(parameters, function(parameter, pi)
					if pi >= real_param_count then return end
					if parameter.IsIn or not parameter.IsOut then 
						in_pos = in_pos + 1
					end
					if parameter.ParameterType.IsByRef then
					%><%=GetPushStatement(parameter.ParameterType:GetElementType(), parameter.Name)%>;
					<%if not parameter.IsOut and parameter.ParameterType.IsByRef and NeedUpdate(parameter.ParameterType) then 
			  %><%=GetUpdateStatement(parameter.ParameterType:GetElementType(), in_pos+param_offset, parameter.Name)%>;
					<%end%>
				<%
					end
				end)
				%>
				<%if NeedUpdate(type) and not method.IsStatic then%>
				<%=GetUpdateStatement(type, 1, "__cl_gen_to_be_invoked")%>;
				<%end%>
				
				return <%=out_num+(has_return and 1 or 0)%>;
			}
			<% end)%>
            <%if method.Overloads.Count > 1 then%>
            return LuaAPI.luaL_error(L, "invalid arguments to <%=CsFullTypeName(type)%>.<%=method.Overloads[0].Name%>!");
            <%end%>
        }
        <% end)%>
        
        
        <%ForEachCsList(getters, function(getter) 
        if getter.IsStatic and getter.ReadOnly then return end --readonly static
        %>
        int <%=v_type_name%>_g_get_<%=getter.Name%><%=generic_arg_list%>(RealStatePtr L, int __gen_param_count) <%=type_constraints%>
        {
            <%if AccessorNeedTranslator(getter) then %>ObjectTranslator translator = this;<%end%>
			<%if not getter.IsStatic then%>
			<%=GetSelfStatement(type)%>;
			<%=GetPushStatement(getter.Type, "__cl_gen_to_be_invoked."..UnK(getter.Name))%>;<% else %>    <%=GetPushStatement(getter.Type, CsFullTypeName(type).."."..UnK(getter.Name))%>;<% end%>
            return 1;
        }
        <%end)%>
        
        <%ForEachCsList(setters, function(setter)
        local is_struct = IsStruct(setter.Type)
        %>
        int <%=v_type_name%>_s_set_<%=setter.Name%><%=generic_arg_list%>(RealStatePtr L, int __gen_param_count) <%=type_constraints%>
        {
            <%if AccessorNeedTranslator(setter) then %>ObjectTranslator translator = this;<%end%>
			<%if not setter.IsStatic then %>
            <%=GetSelfStatement(type)%>;
            <%if is_struct then %><%=GetCasterStatement(setter.Type, 2, "__cl_gen_value", true)%>;
			__cl_gen_to_be_invoked.<%=UnK(setter.Name)%> = __cl_gen_value;<% else 
              %><%=GetCasterStatement(setter.Type, 2, "__cl_gen_to_be_invoked." .. UnK(setter.Name))%>;<%end
            else 
				if is_struct then %><%=GetCasterStatement(setter.Type, 1, "__cl_gen_value", true)%>;
			<%=CsFullTypeName(type)%>.<%=UnK(setter.Name)%> = __cl_gen_value;<%else
          %><%=GetCasterStatement(setter.Type, 1, CsFullTypeName(type) .."." .. UnK(setter.Name))%>;<%end
            end%>
            <%if NeedUpdate(type) and not setter.IsStatic then%>
            <%=GetUpdateStatement(type, 1, "__cl_gen_to_be_invoked")%>;
            <%end%>
            return 0;
        }
        <%end)%>
		
		<%ForEachCsList(events, function(event) if not event.IsStatic then %>
        int <%=v_type_name%>_e_<%=event.Name%><%=generic_arg_list%>(RealStatePtr L, int __gen_param_count) <%=type_constraints%>
        {
            ObjectTranslator translator = this;
			<%=GetSelfStatement(type)%>;
			<%=GetCasterStatement(event.Type, 3, "__gen_delegate", true)%>;
			if (__gen_delegate == null) {
				return LuaAPI.luaL_error(L, "#3 need <%=CsFullTypeName(event.Type)%>!");
			}
			
			if (__gen_param_count == 3)
			{
				<%if event.CanAdd then%>
				if (LuaAPI.xlua_is_eq_str(L, 2, "+")) {
					__cl_gen_to_be_invoked.<%=UnK(event.Name)%> += __gen_delegate;
					return 0;
				} 
				<%end%>
				<%if event.CanRemove then%>
				if (LuaAPI.xlua_is_eq_str(L, 2, "-")) {
					__cl_gen_to_be_invoked.<%=UnK(event.Name)%> -= __gen_delegate;
					return 0;
				} 
				<%end%>
			}
			LuaAPI.luaL_error(L, "invalid arguments to <%=CsFullTypeName(type)%>.<%=event.Name%>!");
            return 0;
        }
        <%end end)%>
		
		<%ForEachCsList(events, function(event) if event.IsStatic then %>
        int <%=v_type_name%>_e_<%=event.Name%><%=generic_arg_list%>(RealStatePtr L, int __gen_param_count) <%=type_constraints%>
        {
            ObjectTranslator translator = this;
			<%=GetCasterStatement(event.Type, 2, "__gen_delegate", true)%>;
			if (__gen_delegate == null) {
				return LuaAPI.luaL_error(L, "#2 need <%=CsFullTypeName(event.Type)%>!");
			}
			
			<%if event.CanAdd then%>
			if (__gen_param_count == 2 && LuaAPI.xlua_is_eq_str(L, 1, "+")) {
				<%=CsFullTypeName(type)%>.<%=UnK(event.Name)%> += __gen_delegate;
				return 0;
			} 
			<%end%>
			<%if event.CanRemove then%>
			if (__gen_param_count == 2 && LuaAPI.xlua_is_eq_str(L, 1, "-")) {
				<%=CsFullTypeName(type)%>.<%=UnK(event.Name)%> -= __gen_delegate;
				return 0;
			} 
			<%end%>
			return LuaAPI.luaL_error(L, "invalid arguments to <%=CsFullTypeName(type)%>.<%=event.Name%>!");
        }
        <%end end)%>
    }
}
