--[[
@ Ziuta
@ 27.02.2015
@ v1.0
@ edit: 28.06.2015
	v1.1: added the ability to load your own texts help
		  added the ability to load button
  edit2: 08.07.2015
	v1.2: added the ability to show/hide help text (F1)
		  added the ability to run animations of the vehicle and on approach

http://landwirtschafts-simulator.pl/
Thanks for your help Koper, lip4 and Decker_MMIV

You can use and edit but keep the original author ;)
]]

--[[
modDesc
<specialization name="animXML" className="animXML" filename="animXML.lua"/>
...
<specialization name="animatedVehicle" />
<specialization name="animXML" /> 

XML-file
<animate>
	<object index="0>0|6" distance="2" animationName="moveSupport" input="support" renderText="true/false" textP="supportUp" textN="supportDown" together="true/false" onApproach="true/false" />
</animate>

INFO:
index - object, relative to which the distance is measured
distance - min distance in meters
animationName - the name of the animation from an XML file
input - the name of a button loaded with modDesc
renderText - displaying the text in the help window (F1) if "true"
textP/textN - text displayed in the help window loaded with modDesc (eg. P- open door, N- close door)
together - the ability to run animations of the vehicle and on approach
onApproach - if "true" animation runs only on the approach, if "false" animation runs only from the vehicle
]]

animXML = {}

function animXML.prerequisitesPresent(specializations)
   return SpecializationUtil.hasSpecialization(AnimatedVehicle, specializations)
end

function animXML:load(xmlFile)	
	self.getIsInRange = animXML.getIsInRange
	self.setAnim = animXML.setAnim
	self.onApproach = {}
	local i = 0
    while true do
		local key = string.format("vehicle.animate.object(%d)", i)
		if not hasXMLProperty(xmlFile, key) then
            break
        end
		local ob = {}
		ob.index = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#index"))
		ob.animationName = getXMLString(xmlFile, key.."#animationName")
		ob.minDistance = Utils.getNoNil(getXMLFloat(xmlFile, key.."#distance"), 2.0)
		ob.input = getXMLString(xmlFile, key.."#input")
		local text = Utils.getNoNil(getXMLBool(xmlFile, key.."#renderText"), true)
		if text then
			ob.text = text
			ob.textP = getXMLString(xmlFile, key.."#textP")
			ob.textN = getXMLString(xmlFile, key.."#textN")
		end
		local together = Utils.getNoNil(getXMLBool(xmlFile, key.."#together"), false)
		if together then
			ob.together = together
		else
			ob.onApp = Utils.getNoNil(getXMLBool(xmlFile, key.."#onApproach"), true)
		end
		ob.animIsChange = false
		table.insert(self.onApproach, ob)
		i = i + 1
	end
end

function animXML:delete()
end

function animXML:readStream(streamId, connection)
	for i=1, table.getn(self.onApproach) do
		local state = streamReadBool(streamId)
		self:setAnim(i, state, true)
	end
end

function animXML:writeStream(streamId, connection)
	for i=1, table.getn(self.onApproach) do
		local ob = self.onApproach[i]
		local state = ob.animIsChange
		streamWriteBool(streamId, state)
	end
end

function animXML:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
	local animChange = getXMLString(xmlFile, key.."#animationChange")
	local obj = false
	local t = 0
	if animChange ~= nil then
		local ob = Utils.splitString(" ", animChange)		
		for i=1, table.getn(self.onApproach) do
			if ob[i] == "true" then
				obj = true
				t = 1
			elseif ob[i] == "false" then
				obj = false
				t = 0
			end
			local state = obj
			self:setAnim(i, state)
			self:setAnimationTime(self.onApproach[i].animationName,t,true)
		end
	elseif animChange == nil then
		for i=1, table.getn(self.onApproach) do
			self:setAnim(i, obj)
			self:setAnimationTime(self.onApproach[i].animationName,t,true)
		end
	end	
	return BaseMission.VEHICLE_LOAD_OK
end

function animXML:getSaveAttributesAndNodes(nodeIdent)
	local attributes = 'animationChange="'
	for i=1, table.getn(self.onApproach) do
		local ob = self.onApproach[i]
		local state = ob.animIsChange
		attributes = attributes..tostring(state).." "
	end
	attributes = attributes..'"'
	return attributes, ""
end

function animXML:mouseEvent(posX, posY, isDown, isUp, button)
end

function animXML:keyEvent(unicode, sym, modifier, isDown)
end

function animXML:update(dt)
	if self.isClient then
		for i=1, table.getn(self.onApproach) do
			if self.onApproach[i].together then
				if self:getIsInRange(i) then
					if InputBinding.hasEvent(InputBinding[self.onApproach[i].input]) then
						self:setAnim(i, not self.onApproach[i].animIsChange)
					end
					if self.onApproach[i].text then
						if self.onApproach[i].animIsChange then
							g_currentMission:addHelpButtonText(g_i18n:getText(self.onApproach[i].textN), InputBinding[self.onApproach[i].input])
						else
							g_currentMission:addHelpButtonText(g_i18n:getText(self.onApproach[i].textP), InputBinding[self.onApproach[i].input])
						end
					end
				elseif self:getIsActiveForInput(true) then
					if InputBinding.hasEvent(InputBinding[self.onApproach[i].input]) then
						self:setAnim(i, not self.onApproach[i].animIsChange)
					end
					if self.onApproach[i].text then
						if self.onApproach[i].animIsChange then
							g_currentMission:addHelpButtonText(g_i18n:getText(self.onApproach[i].textN), InputBinding[self.onApproach[i].input])
						else
							g_currentMission:addHelpButtonText(g_i18n:getText(self.onApproach[i].textP), InputBinding[self.onApproach[i].input])
						end
					end
				end				
			else
				if self.onApproach[i].onApp then
					if self:getIsInRange(i) then
						if InputBinding.hasEvent(InputBinding[self.onApproach[i].input]) then
							self:setAnim(i, not self.onApproach[i].animIsChange)
						end
						if self.onApproach[i].text then
							if self.onApproach[i].animIsChange then
								g_currentMission:addHelpButtonText(g_i18n:getText(self.onApproach[i].textN), InputBinding[self.onApproach[i].input])
							else
								g_currentMission:addHelpButtonText(g_i18n:getText(self.onApproach[i].textP), InputBinding[self.onApproach[i].input])
							end
						end
					end
				elseif not self.onApproach[i].onApp and self:getIsActiveForInput(true) then
					if InputBinding.hasEvent(InputBinding[self.onApproach[i].input]) then
						self:setAnim(i, not self.onApproach[i].animIsChange)
					end
					if self.onApproach[i].text then
						if self.onApproach[i].animIsChange then
							g_currentMission:addHelpButtonText(g_i18n:getText(self.onApproach[i].textN), InputBinding[self.onApproach[i].input])
						else
							g_currentMission:addHelpButtonText(g_i18n:getText(self.onApproach[i].textP), InputBinding[self.onApproach[i].input])
						end
					end
				end
			end
		end
	end
end

function animXML:draw()
end

function animXML:getIsInRange(i)
	local rx, ry, rz = getWorldTranslation(g_currentMission.player.rootNode)
	local ox, oy, oz = getWorldTranslation(self.onApproach[i].index)
	local distance = Utils.vector3Length(rx-ox, ry-oy, rz-oz)

	if distance <= self.onApproach[i].minDistance then
		return true
	else
		return false
	end
end

function animXML:setAnim(index, state, noEventSend)
	setAnimEvent.sendEvent(self, index, state, noEventSend)
	local ob = self.onApproach[index]
	local animTime = self:getAnimationTime(ob.animationName)
	if state and animTime < 1 then
		self:playAnimation(ob.animationName,1,animTime,true)
	elseif animTime > 0 then
		self:playAnimation(ob.animationName,-1,animTime,true)
	end
	ob.animIsChange = state
end

--
-- MP ready
--

setAnimEvent = {}
setAnimEvent_mt = Class(setAnimEvent, Event)

InitEventClass(setAnimEvent, "setAnimEvent")

function setAnimEvent:emptyNew()
    local self = Event:new(setAnimEvent_mt)
    return self
end

function setAnimEvent:new(object, index, state)
    local self = setAnimEvent:emptyNew()
    self.object = object
    self.index = index
	self.state = state
    return self
end

function setAnimEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId)
	self.object = networkGetObject(id)	
	self.index = streamReadInt8(streamId)
	self.state = streamReadBool(streamId)	
    self:run(connection)
end

function setAnimEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.object))
	streamWriteInt8(streamId, self.index)
	streamWriteBool(streamId, self.state)
end;

function setAnimEvent:run(connection)
    self.object:setAnim(self.index, self.state, true)
    if not connection:getIsServer() then
        g_server:broadcastEvent(setAnimEvent:new(self.object, self.index, self.state), nil, connection, self.object)
    end
end

function setAnimEvent.sendEvent(vehicle, index, state, noEventSend)
	if noEventSend == nil or noEventSend == false then
		if g_server ~= nil then
			g_server:broadcastEvent(setAnimEvent:new(vehicle, index, state), nil, nil, vehicle)
		else
			g_client:getServerConnection():sendEvent(setAnimEvent:new(vehicle, index, state))
		end
	end
end