
r2.Features.ZoneTrigger = {}

local feature = r2.Features.ZoneTrigger 

feature.Name="ZoneTrigger"


feature.Description="Triggers an event when a player enters or leaves a zone"

feature.Components = {}

local classZoneTriggerVersion = 1

feature.Components.ZoneTrigger =
	{
		PropertySheetHeader = r2.getDisplayButtonHeader("r2.events:openEditor()", "uiR2EdEditEventsButton"),
		BaseClass="LogicEntity",			
		Name="ZoneTrigger",
		InEventUI = true,
		Menu="ui:interface:r2ed_feature_menu",
		Version=classZoneTriggerVersion ,
		DisplayerUI = "R2::CDisplayerLua",
		DisplayerUIParams = "defaultUIDisplayer",
		DisplayerVisual = "R2::CDisplayerVisualEntity",
		-----------------------------------------------------------------------------------------------	
		Parameters = {},
		ApplicableActions = {
			"activate", "deactivate", "simulate on enter", "simulate on leave"
		},
		Events = {
			"On Player Arrived", 
			"On Player Left",
			"activation", "deactivation"
	--		"On First Player Arrived", 
	--		"On First Player Left",			
		},
		Conditions = {"is active", "is inactive", "is empty", "is full"},
		TextContexts =		{},
		TextParameters =	{},
		LiveParameters =	{},
		-----------------------------------------------------------------------------------------------	
		Prop =
		{
			{Name="InstanceId", Type="String", WidgetStyle="StaticText", Visible = false},
			{Name="Name", Type="String", MaxNumChar="32"},
			{Name="Cyclic", Type="Number", WidgetStyle="Boolean", DefaultValue="1"},
			{Name="Active", Type="Number", WidgetStyle="Boolean", DefaultValue="1"},
			{Name="Components", Type="Table"}		
		
		},

		getAvailableCommands = function(this, dest)	
			r2.Classes.LogicEntity.getAvailableCommands(this, dest) -- fill by ancestor
			this:getAvailableDisplayModeCommands(dest)
		end,
		-----------------------------------------------------------------------------------------------		
		-- from base class
		getParentTreeNode = function(this)
			return this:getFeatureParentTreeNode()
		end,
		---------------------------------------------------------------------------------------------------------
		-- from base class			
		appendInstancesByType = function(this, destTable, kind)
			assert(type(kind) == "string")
			--this:delegate():appendInstancesByType(destTable, kind)
			r2.Classes.LogicEntity.appendInstancesByType(this, destTable, kind)
			for k, component in specPairs(this.Components) do
				component:appendInstancesByType(destTable, kind)
			end
		end,
		---------------------------------------------------------------------------------------------------------
		-- from base class
		getSelectBarSons = function(this)
			return Components
		end,
		---------------------------------------------------------------------------------------------------------
		-- from base class		
		canHaveSelectBarSons = function(this)
			return false;
		end,		

		onPostCreate = function(this)
			--this:createGhostComponents()
			if this.User.DisplayProp and this.User.DisplayProp == 1 then
				r2:setSelectedInstanceId(this.InstanceId)				
				r2:showProperties(this)		
				this.User.DisplayProp = nil
			end
		end,


		pretranslate = function(this, context)
			local rtNpcGrp, aiState = r2.Translator.createAiGroup(this, context)
			local zone = r2:getInstanceFromId(this._Zone)
			Logic.assignZone(aiState, zone)
			aiState.IsTriggerZone = 1
		end,

		translate = function(this, context)

			local instance = this		
			local instanceId =  this.InstanceId
			local rtNpcGrp = r2.Translator.getRtGroup(context, instanceId)
			local states = r2.Translator.getRtStatesNames(context, instanceId)

		

			
			
			do	
				local eventHandler = r2.Translator.createEvent("on_player_arrived", states,  rtNpcGrp.Id)
				eventHandler.IsTriggerZone = 1
				local action =  r2.Translator.createAction("on_player_arrived_impl", rtNpcGrp.Id)

				table.insert(context.RtAct.Events, eventHandler)		
				-- insert a npc_event_handler_action
				table.insert(eventHandler.ActionsId, action.Id)
				table.insert(context.RtAct.Actions, action)
			end

			do	
				local eventHandler = r2.Translator.createEvent("on_player_left", states,  rtNpcGrp.Id)
				eventHandler.IsTriggerZone = 1
				local action =  r2.Translator.createAction("on_player_left_impl", rtNpcGrp.Id)

				table.insert(context.RtAct.Events, eventHandler)		
				-- insert a npc_event_handler_action
				table.insert(eventHandler.ActionsId, action.Id)
				table.insert(context.RtAct.Actions, action)
			end

			do
				local eventHandler  =r2.Translator.createEvent("start_of_state", states,  rtNpcGrp.Id)
				eventHandler.IsTriggerZone = 1
				local action = r2.Translator.createAction("trigger_zone_init", rtNpcGrp.Id, instance.Active, instance.Cyclic )

				table.insert(context.RtAct.Events, eventHandler)		
				-- insert a npc_event_handler_action
				table.insert(eventHandler.ActionsId, action.Id)
				table.insert(context.RtAct.Actions, action)
			end
		
			-- AdD
			r2.Translator.translateAiGroup(this, context)
			--r2.Translator.translateEventHandlers( context, instance, instance.Behavior.Actions, rtNpcGrp)
		
		end,

	updateVersion = function(this, scenarioValue, currentValue )
			local patchValue = scenarioValue
			if patchValue < 1 then
				if not this.Active then r2.requestSetNode(this.InstanceId, "Active", 1)	end
				if not this.Cyclic then r2.requestSetNode(this.InstanceId, "Cyclic", 1)	end
				patchValue = 1
			end
			
			if patchValue == currentValue then return true end
			return false
		end,		


	}

-- Specific to the component Zone
local component = feature.Components.ZoneTrigger  


component.getLogicAction = function(entity, context, action)
	
	assert( action.Class == "ActionStep") 
	local component = r2:getInstanceFromId(action.Entity)
	assert(component)
	local rtNpcGrp = r2.Translator.getRtGroup(context, component.InstanceId)
	assert(rtNpcGrp)


	local theType = action.Action.Type
	local retAction = nil
	if theType == "activate" then 
		retAction = r2.Translator.createAction("if_value_equal", rtNpcGrp.Id, "Active", 0, 
			r2.Translator.createAction("trigger_zone_activates", rtNpcGrp.Id))
	elseif theType == "deactivate" then		
		retAction = r2.Translator.createAction("if_value_equal", rtNpcGrp.Id, "Active", 1,
			r2.Translator.createAction("trigger_zone_deactivates", rtNpcGrp.Id))
	elseif theType == "simulate on enter" then		
		retAction = r2.Translator.createAction("if_value_equal", rtNpcGrp.Id, "Active", 1,
			r2.Translator.createAction("user_event_trigger", rtNpcGrp.Id, 1))
	elseif theType == "simulate on leave" then		
		retAction = r2.Translator.createAction("if_value_equal", rtNpcGrp.Id, "Active", 1,
			r2.Translator.createAction("user_event_trigger", rtNpcGrp.Id, 2))

	end
	
	return retAction, retAction
end

component.getLogicCondition = function(this, context, condition)
	assert( condition.Class == "ConditionStep") 
	local component = r2:getInstanceFromId(condition.Entity)
	assert(component)
	local rtNpcGrp = r2.Translator.getRtGroup(context, component.InstanceId)
	assert(rtNpcGrp)
	local states = r2.Translator.getRtStatesNames(context, component.InstanceId)
	assert(states)

	local theType = condition.Condition.Type
	if theType == "is empty" then
		local retAction = r2.Translator.createAction("trigger_zone_min_player", rtNpcGrp.Id, states, 0)
		return retAction, retAction
	elseif theType == "is full" then
		local retAction = r2.Translator.createAction("trigger_zone_min_player", rtNpcGrp.Id, states, 1)
		return retAction, retAction
	end


	return r2.Translator.getFeatureActivationCondition(condition, rtNpcGrp)
end

component.getLogicEvent = function(this, context, event)
	assert( event.Class == "LogicEntityAction") 

	local component =  this -- r2:getInstanceFromId(event.Entity)
	assert(component)
	local rtNpcGrp = r2.Translator.getRtGroup(context, component.InstanceId)
	assert(rtNpcGrp)

	local eventType = tostring(event.Event.Type)
	
	local eventHandler, lastCondition = nil, nil
			
	if eventType == "On Player Arrived" then 
		local e, c1, c2 =r2.Translator.getComponentUserEvent(rtNpcGrp, 1);
		e.IsTriggerZone = 1
		return e, c1, c2
	elseif eventType == "On Player Left" then
		local e, c1, c2 = r2.Translator.getComponentUserEvent(rtNpcGrp, 2);
		e.IsTriggerZone = 1
		return e, c1, c2
	elseif eventType == "activation" then
		e, c1, c2 = r2.Translator.getComponentUserEvent(rtNpcGrp, 4)
		e.IsTriggerZone = 1
		return e, c1, c2
	elseif eventType == "deactivation" then
		e, c1, c2 = r2.Translator.getComponentUserEvent(rtNpcGrp, 5)
		e.IsTriggerZone = 1
		return e, c1, c2
 	end
	return eventHandler, firstCondition, lastCondition
end


local ZoneTriggerRadius = 5
local ZoneTriggerNumCorners = 4

component.createComponent = function(x, y)
	
	local comp = r2.newComponent("ZoneTrigger")
	assert(comp)
	assert(comp.Position)

	comp.Base = r2.Translator.getDebugBase("palette.entities.botobjects.trigger_zone")
	comp.Name = r2:genInstanceName(i18n.get("uiR2EDRollout_ZoneTrigger"))			
	
	comp.Position.x = x
	comp.Position.y = y
	comp.Position.z = r2:snapZToGround(x, y)

	local zone = r2.newComponent("Region")
	r2.Utils.createTriggerRegion(zone, 0, 0, ZoneTriggerRadius) -- the region doesn't inherit the feature position, so must give its pos
	zone.Deletable = 0
	zone.Position.x = 0 -- comp.Position.x
	zone.Position.y = 0 --  comp.Position.y
	zone.Position.z = 0 -- comp.Position.z
	zone.InheritPos = 1 -- don't inherit position of parents
	zone.Name = r2:genInstanceName(i18n.get("uiR2EDPlaces"))			
	comp._Zone = zone.InstanceId
	table.insert(comp.Components, zone)

	
	return comp
end

component.create = function()	

	if not r2:checkAiQuota() then return end

	local function paramsOk(resultTable)

		r2.requestNewAction(i18n.get("uiR2EDNewZoneTriggersFeatureAction"))

		local x = tonumber(  resultTable["X"] )
		local y = tonumber( resultTable["Y"] )
		local showAgain = tonumber(resultTable["Display"])

		if not x or not y 		then
			debugInfo("Can't create Component")
			return
		end
		
		if showAgain == 1 then 
			r2.setDisplayInfo("ZoneForm", 0)
		else r2.setDisplayInfo("ZoneForm", 1) end


		local component = feature.Components.ZoneTrigger.createComponent( x, y)
		r2:setCookie(component.InstanceId, "DisplayProp", 1)
		r2.requestInsertNode(r2:getCurrentAct().InstanceId, "Features", -1, "", component)	
	end

	local function posOk(x, y, z)
		debugInfo("Validate creation of a Zone Trigger.")
		if r2.mustDisplayInfo("ZoneTrigger") == 1 then 
			r2.displayFeatureHelp("ZoneTrigger")
		end
		r2.requestNewAction(i18n.get("uiR2EDNewZoneTriggersFeatureAction"))
		local component = feature.Components.ZoneTrigger.createComponent( x, y)
		r2:setCookie(component.InstanceId, "DisplayProp", 1)
		r2.requestInsertNode(r2:getCurrentAct().InstanceId, "Features", -1, "", component)	
	end

	local function posCancel()	end

	local creature = r2.Translator.getDebugCreature("object_component_trigger_zone.creature") 
	--r2:choosePos(creature, posOk, posCancel, "createFeatureZoneTrigger")

	local poly = {}
	local step = 2 * math.pi / ZoneTriggerNumCorners
	for k = 0, ZoneTriggerNumCorners - 1 do
		table.insert(poly, CVector2f(ZoneTriggerRadius * math.cos(k * step), ZoneTriggerRadius * math.sin(k * step)))
	end	
	r2:choosePos(creature, posOk, posCancel, "createFeatureZoneTrigger", 
				 "curs_create.tga",
				 "curs_stop.tga",
	             { poly }, r2.PrimRender.ComponentRegionLook, r2.PrimRender.ComponentRegionInvalidLook)


end


function feature.registerForms()
	r2.Forms.ZoneForm =
	{
		Caption = "uiR2EdTriggerZoneParameters",
		PropertySheetHeader = 
		[[
			<view type="text" id="t" multi_line="true" sizeref="w" w="-36" x="4" y="-2" posref="TL TL" global_color="true" fontsize="14" shadow="true" hardtext="uiR2EDTriggerZoneDescription"/>
		]],
		Prop =
		{
			{Name="Display", Type="Number", WidgetStyle="Boolean", DefaultValue="0", Translation="uiR2showMessageAgain", InvertWidget=true, CaptionWidth=5 },
		}
	}

end

-----------------------------------------
--- register the curent Feature to menu

function component:getLogicTranslations()
	-- register trad
	local logicTranslations = {
		["ApplicableActions"] = {	
			["activate"]				= { menu=i18n.get( "uiR2AA0Activate"			), 
											text=i18n.get( "uiR2AA1Activate"			)}, 
			["deactivate"]				= { menu=i18n.get( "uiR2AA0Deactivate"			), 
											text=i18n.get( "uiR2AA1Deactivate"			)}, 
			["simulate on enter"]		= { menu=i18n.get( "uiR2AA0ZoneTriggerSimEnter"	), 
											text=i18n.get( "uiR2AA1ZoneTriggerSimEnter"	)},
			["simulate on leave"]		= { menu=i18n.get( "uiR2AA0ZoneTriggerSimExit"	), 
											text=i18n.get( "uiR2AA1ZoneTriggerSimExit"	)},
		},
		["Events"] = {
			["activation"]				= { menu=i18n.get( "uiR2Event0Activation"		), 
											text=i18n.get( "uiR2Event1Activation"		)},
			["deactivation"]			= { menu=i18n.get( "uiR2Event0Deactivation"		), 
											text=i18n.get( "uiR2Event1Deactivation"		)},
			["On Player Arrived"]		= { menu=i18n.get( "uiR2Event0ZoneTriggerEntry"	), 
											text=i18n.get( "uiR2Event1ZoneTriggerEntry"	)},
			["On Player Left"]			= { menu=i18n.get( "uiR2Event0ZoneTriggerExit"	), 
											text=i18n.get( "uiR2Event1ZoneTriggerExit"	)},
		},
		["Conditions"] = {
			["is active"]				= { menu=i18n.get( "uiR2Test0Active"			), 
											text=i18n.get( "uiR2Test1Active"			)},
			["is inactive"]				= { menu=i18n.get( "uiR2Test0Inactive"			), 
											text=i18n.get( "uiR2Test1Inactive"			)},
			["is empty"]				= { menu=i18n.get( "uiR2Test0ZoneTriggerEmpty"			), 
											text=i18n.get( "uiR2Test1ZoneTriggerEmpty"			)},
			["is full"]				= { menu=i18n.get( "uiR2Test0ZoneTriggerFull"			), 
											text=i18n.get( "uiR2Test1ZoneTriggerFull"			)},


		}
	}

	return logicTranslations
end

r2.Features["ZoneTrigger"] =  feature



