local metadata = {
"## Interface:FS15 1.4.2.0 1.4.2RC1",
"## Title: AutoLoadWood",
"## Notes: AutoLoadWood",
"## Author: Marhu",
"## Version: 0.3.0-162",
"## Date: 19.02.2016",
"## Web: http://marhu.net"
} 

local function L(name)
	return g_i18n:hasText("AutoLoadWood_"..name) and g_i18n:getText("AutoLoadWood_"..name) or name;
end

AutoLoadWood = {};
AutoLoadWood.Dir = g_currentModDirectory;
		
function AutoLoadWood.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(DynamicMountAttacher, specializations)
end;

function AutoLoadWood:load(xmlFile)

    self.toggleState = SpecializationUtil.callSpecializationsFunction("toggleState");
	
	self.doCheckSpeedLimit = Utils.overwrittenFunction(self.doCheckSpeedLimit, AutoLoadWood.doCheckSpeedLimit)
	self.dynamicMountTriggerCallback =  Utils.overwrittenFunction(self.dynamicMountTriggerCallback, AutoLoadWood.dynamicMountTriggerCallback)
	
	self.woodLoad = {};
	self.autoload = false;
	self.rightSide = false;
	self.unload = false;
	
	self.searchSizeY = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.AutoLoadWood#SizeY"),5);
	self.searchSizeZ = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.AutoLoadWood#SizeX"),10);
	self.autoLoadSpeed = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.AutoLoadWood#Speed"),300);
	self.autoLoadElaps = 0;
	
	if self.isServer then
		
		local key = "vehicle.AutoLoadWood.woodTrigger";
		local woodTriggerXOff = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#xOff"),1.2);
		local woodTriggerYOff = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#yOff"),-3);
		local woodTriggerZOff = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#zOff"),1.5);
		
		local key = "vehicle.AutoLoadWood.fillPose";
		local fillPoseXOff = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#xOff"),0);
		local fillPoseYOff = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#yOff"),2);
		local fillPoseZOff = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#zOff"),0);
		
		local key = "vehicle.AutoLoadWood.unloadPose";
		local unloadPoseXOff = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#xOff"),3);
		local unloadPoseYOff = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#yOff"),0);
		local unloadPoseZOff = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#zOff"),0);
		
		local linkNode = getParent(self.dynamicMountAttacherTrigger.triggerNode)
		local x,y,z = getTranslation(self.dynamicMountAttacherTrigger.triggerNode)
		
		self.woodTrigger = {createTransformGroup("woodTrigger1"),
							createTransformGroup("woodTrigger2"),
							createTransformGroup("woodTrigger3"),
							createTransformGroup("woodTrigger4")};
		
		local rot = math.rad(90)
		for i = 1, 4 do					
			link(linkNode, self.woodTrigger[i]);
			setTranslation(self.woodTrigger[i], x + woodTriggerXOff, y + woodTriggerYOff, z + woodTriggerZOff)
			setRotation(self.woodTrigger[i], 0, rot, 0);
			woodTriggerZOff = woodTriggerZOff * -1;
			if i == 2 then 
				woodTriggerXOff = woodTriggerXOff * -1;
				rot = math.rad(-90)
			end
		end
			
		self.fillPoseNode = createTransformGroup("fillPoseNode");
		link(linkNode,self.fillPoseNode);
		setTranslation(self.fillPoseNode, x + fillPoseXOff, y + fillPoseYOff, z + fillPoseZOff)
		setRotation(self.fillPoseNode,math.rad(-90),0,0)
		
		self.unloadPoseNode = {	createTransformGroup("unloadPoseNode1"),
								createTransformGroup("unloadPoseNode2")};
		
		for i = 1, 2 do					
			link(linkNode, self.unloadPoseNode[i]);
			setTranslation(self.unloadPoseNode[i], x + unloadPoseXOff, y + unloadPoseYOff, z + unloadPoseZOff)
			setRotation(self.unloadPoseNode[i],math.rad(-90),0,0)
			unloadPoseXOff = unloadPoseXOff * -1;
		end
	end;
end;

function AutoLoadWood:delete()
	
end;

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

function AutoLoadWood:keyEvent(unicode, sym, modifier, isDown)
end;

function AutoLoadWood:update(dt)
	if self:getIsActiveForInput() then
		if InputBinding.hasEvent(InputBinding.AUTOLOADWOOD_TOGGLE_AUTO) then
			self:toggleState(not self.autoload, self.rightSide, false)
		end;
		if InputBinding.hasEvent(InputBinding.AUTOLOADWOOD_TOGGLE_UNLOAD) then
			self:toggleState(false, self.rightSide, not self.unload)
		end
		if InputBinding.hasEvent(InputBinding.AUTOLOADWOOD_TOGGLE_SIDE) then
			self:toggleState(false, not self.rightSide, false)
		end
	end;
	
	if false then
		for i = 1, 4 do
			local x,y,z = getWorldTranslation(self.woodTrigger[i])
			local nx, ny, nz = localDirectionToWorld(self.woodTrigger[i], 1, 0, 0)
			local yx, yy, yz = localDirectionToWorld(self.woodTrigger[i], 0, 1, 0)
			local zx, zy, zz = localDirectionToWorld(self.woodTrigger[i], 0, 0, 1)
			drawDebugLine(x,y,z, 1, 0, 0, x + nx, y + ny, z + nz, 1, 0, 0);
			drawDebugLine(x,y,z, 0, 1, 0, x + yx, y + yy, z + yz, 0, 1, 0);
			drawDebugLine(x,y,z, 0, 0, 1, x + zx, y + zy, z + zz, 0, 0, 1);
		end
		
		local x,y,z = getWorldTranslation(self.fillPoseNode)
		local nx, ny, nz = localDirectionToWorld(self.fillPoseNode, 1, 0, 0)
		local yx, yy, yz = localDirectionToWorld(self.fillPoseNode, 0, 1, 0)
		local zx, zy, zz = localDirectionToWorld(self.fillPoseNode, 0, 0, 1)
		drawDebugLine(x,y,z, 1, 0, 0, x + nx, y + ny, z + nz, 1, 0, 0);
		drawDebugLine(x,y,z, 0, 1, 0, x + yx, y + yy, z + yz, 0, 1, 0);
		drawDebugLine(x,y,z, 0, 0, 1, x + zx, y + zy, z + zz, 0, 0, 1);
		
		for i = 1, 2 do
			local x,y,z = getWorldTranslation(self.unloadPoseNode[i])
			local nx, ny, nz = localDirectionToWorld(self.unloadPoseNode[i], 1, 0, 0)
			local yx, yy, yz = localDirectionToWorld(self.unloadPoseNode[i], 0, 1, 0)
			local zx, zy, zz = localDirectionToWorld(self.unloadPoseNode[i], 0, 0, 1)
			drawDebugLine(x,y,z, 1, 0, 0, x + nx, y + ny, z + nz, 1, 0, 0);
			drawDebugLine(x,y,z, 0, 1, 0, x + yx, y + yy, z + yz, 0, 1, 0);
			drawDebugLine(x,y,z, 0, 0, 1, x + zx, y + zy, z + zz, 0, 0, 1);
		end
		
		if self.lastWoodShapes ~= nil and entityExists(self.lastWoodShapes) then
			local x,y,z = getWorldTranslation(self.lastWoodShapes)
			local nx, ny, nz = localDirectionToWorld(self.lastWoodShapes, 10, 0, 0)
			local yx, yy, yz = localDirectionToWorld(self.lastWoodShapes, 0, 10, 0)
			local zx, zy, zz = localDirectionToWorld(self.lastWoodShapes, 0, 0, 10)
			drawDebugLine(x,y,z, 1, 0, 0, x + nx, y + ny, z + nz, 1, 0, 0);
			drawDebugLine(x,y,z, 0, 1, 0, x + yx, y + yy, z + yz, 0, 1, 0);
			drawDebugLine(x,y,z, 0, 0, 1, x + zx, y + zy, z + zz, 0, 0, 1);
		end
	end
end;

function AutoLoadWood:updateTick(dt)
	
	if self.autoload then
		self.autoLoadElaps = self.autoLoadElaps + dt;
		if self.autoLoadElaps >= self.autoLoadSpeed then
			self.autoLoadElaps = 0;
			
			if self.isServer then
				if entityExists(self.lastWoodShapes) and self.woodLoad[self.lastWoodShapes] == nil then
					self:toggleState(false, self.rightSide, self.unload)
					return;
				end;
				
				local triggerNum = (self.rightSide and 2 or 0) + 1;
				
				local x,y,z = getWorldTranslation(self.woodTrigger[triggerNum])
				local nx, ny, nz = localDirectionToWorld(self.woodTrigger[triggerNum], 1, 0, 0)
				local yx, yy, yz = localDirectionToWorld(self.woodTrigger[triggerNum], 0, 1, 0)
				local shape, minY, maxY, minZ, maxZ = findSplitShape(x, y, z, nx, ny, nz, yx, yy, yz, self.searchSizeY, self.searchSizeZ)
				
				if shape == nil or not entityExists(shape) or getRigidBodyType(shape) ~= "Dynamic" then
					triggerNum = triggerNum + 1;
					x,y,z = getWorldTranslation(self.woodTrigger[triggerNum])
					nx, ny, nz = localDirectionToWorld(self.woodTrigger[triggerNum], 1, 0, 0)
					yx, yy, yz = localDirectionToWorld(self.woodTrigger[triggerNum], 0, 1, 0)
					shape, minY, maxY, minZ, maxZ = findSplitShape(x, y, z, nx, ny, nz, yx, yy, yz, self.searchSizeY, self.searchSizeZ)
				end	
				
				if shape ~= nil and entityExists(shape) and getRigidBodyType(shape) == "Dynamic" then
					local sizeX, sizeY, sizeZ, numConvexes = getSplitShapeStats(shape)
					local a, b, c = localToWorld(self.woodTrigger[triggerNum], 0, (minY + maxY)*0.5, (minZ + maxZ)*0.5)
					local sx,sy,sz = getWorldTranslation(shape)
					local dist = Utils.vector3Length(a - sx, b - sy, c - sz)
					local nx, ny, nz = localDirectionToWorld(shape, 0, 1, 0)
					local lenBelow, lenAbove = getSplitShapePlaneExtents(shape, a, b, c, nx, ny, nz);
					dist = dist - lenBelow
					local wx,wy,wz = localToWorld(self.fillPoseNode,0,-dist - (sizeX/2),0)
					local dx,dy,dz = worldToLocal(getParent(shape),wx,wy,wz)
					local nx, ny, nz = localDirectionToWorld(self.fillPoseNode, 1, 0, 0)
					local yx, yy, yz = localDirectionToWorld(self.fillPoseNode, 0, 1, 0)
					local x, y, z = worldDirectionToLocal(getParent(shape), nx, ny, nz)
					local xdir, ydir, zdir = worldDirectionToLocal(getParent(shape), yx, yy, yz)
					removeFromPhysics(shape)
					setTranslation(shape,dx,dy,dz)
					setDirection(shape, x, y, z, xdir, ydir, zdir)
					addToPhysics(shape)
					self.lastWoodShapes = shape
				end
			end
		end
	elseif self.unload then
		self.autoLoadElaps = self.autoLoadElaps + dt;
		if self.autoLoadElaps >= self.autoLoadSpeed then
			self.autoLoadElaps = 0;
			
			if self.isServer then
				local x,y,z = getWorldTranslation(self.fillPoseNode)
				local findWood = false;
				for k, shape in pairs(self.woodLoad) do
					if entityExists(shape) then
						local side = self.rightSide and 2 or 1;
						local sx,sy,sz = getWorldTranslation(shape)
						local dist = Utils.vector2Length(x - sx, z - sz)
						if dist < 100 then
							local wx,wy,wz = localToWorld(self.unloadPoseNode[side],0,-dist,0)
							local dx,dy,dz = worldToLocal(getParent(shape),wx,wy,wz)
							local nx, ny, nz = localDirectionToWorld(self.unloadPoseNode[side], 1, 0, 0)
							local yx, yy, yz = localDirectionToWorld(self.unloadPoseNode[side], 0, 1, 0)
							local x, y, z = worldDirectionToLocal(getParent(shape), nx, ny, nz)
							local xdir, ydir, zdir = worldDirectionToLocal(getParent(shape), yx, yy, yz)
							removeFromPhysics(shape)
							setTranslation(shape,dx,dy,dz)
							setDirection(shape, x, y, z, xdir, ydir, zdir)
							addToPhysics(shape)
							self:dynamicMountTriggerCallback(self.dynamicMountAttacherTrigger.triggerNode, shape, false, true, false, shape)
							findWood = true;
							break;
						else
							self.woodLoad[k] = nil
						end
					else
						self.woodLoad[k] = nil
					end
				end
				if findWood == false then self:toggleState(self.autoload, self.rightSide, false) end;
			end;
		end;
	end
end

function AutoLoadWood:readStream(streamId, connection)
    
end;

function AutoLoadWood:writeStream(streamId, connection)
   
end;

function AutoLoadWood:readUpdateStream(streamId, timestamp, connection)
			 
end;

function AutoLoadWood:writeUpdateStream(streamId, connection, dirtyMask)
	
end;

function AutoLoadWood:draw()
	if self.isClient and self:getIsActiveForInput() then
		if self.autoload then
			g_currentMission:addHelpButtonText(L("OFF"), InputBinding.AUTOLOADWOOD_TOGGLE_AUTO);
		else
			g_currentMission:addHelpButtonText(L("ON"), InputBinding.AUTOLOADWOOD_TOGGLE_AUTO);
		end
		if self.unload then
			g_currentMission:addHelpButtonText(L("stopUnload"), InputBinding.AUTOLOADWOOD_TOGGLE_UNLOAD);
		else
			g_currentMission:addHelpButtonText(L("unload"), InputBinding.AUTOLOADWOOD_TOGGLE_UNLOAD);
		end
		if self.rightSide then
			g_currentMission:addHelpButtonText(L("right"), InputBinding.AUTOLOADWOOD_TOGGLE_SIDE);
		else
			g_currentMission:addHelpButtonText(L("left"), InputBinding.AUTOLOADWOOD_TOGGLE_SIDE);	
		end
	end;
end;

function AutoLoadWood:onAttach()
end; 

function AutoLoadWood:onDetach()
	
end;

function AutoLoadWood:onLeave()
	
end

function AutoLoadWood:getSaveAttributesAndNodes(nodeIdent)

	local attributes = "";
    local nodes = "";
  	
	return attributes,nodes;
end

function AutoLoadWood:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
	return BaseMission.VEHICLE_LOAD_OK;
end

function AutoLoadWood:toggleState(autoload, rightSide, unload, noEventSend)

	AutoLoadWoodToggleEvent.sendEvent(self, autoload, rightSide, unload, noEventSend)
	
	self.lastWoodShapes = 0;
	self.autoload = autoload;
	self.rightSide = rightSide;
	self.unload = unload;
	
end;

function AutoLoadWood:doCheckSpeedLimit(superFunc)
	local parent = true

	if superFunc ~= nil then
		parent = superFunc(self)
	end
	
	return parent and (self.autoload or self.unload);
end

function AutoLoadWood:getDefaultSpeedLimit()
	return 10
end

function AutoLoadWood:dynamicMountTriggerCallback(superFunc,triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId)
	local splitType = SplitUtil.splitTypes[getSplitType(otherActorId)]
	if splitType ~= nil then
		if onEnter then
			self.woodLoad[otherActorId] = otherActorId
			--print("onEnter: ",otherActorId)
		elseif onLeave then
			self.woodLoad[otherActorId] = nil;
			--print("onLeave: ",otherActorId)
		end
	end
	superFunc(self, triggerId, otherActorId, onEnter, onLeave, onStay, otherShapeId)
end

--- Event ---

AutoLoadWoodToggleEvent = {};
AutoLoadWoodToggleEvent_mt = Class(AutoLoadWoodToggleEvent, Event);

InitEventClass(AutoLoadWoodToggleEvent, "AutoLoadWoodToggleEvent");

function AutoLoadWoodToggleEvent:emptyNew()
    local self = Event:new(AutoLoadWoodToggleEvent_mt);
    return self;
end;
    
function AutoLoadWoodToggleEvent:new(object, autoload, rightSide, unload)
	local self = AutoLoadWoodToggleEvent:emptyNew()
	self.object = object;
	self.autoload = autoload;
	self.rightSide = rightSide;
	self.unload = unload;
	return self;
end;

function AutoLoadWoodToggleEvent:readStream(streamId, connection)
	local id = streamReadInt32(streamId);
	self.autoload = streamReadBool(streamId);
	self.rightSide = streamReadBool(streamId);
	self.unload = streamReadBool(streamId);
	self.object = networkGetObject(id);
	self:run(connection);
end;

function AutoLoadWoodToggleEvent:writeStream(streamId, connection)
	streamWriteInt32(streamId, networkGetObjectId(self.object));
	streamWriteBool(streamId, self.autoload);
	streamWriteBool(streamId, self.rightSide);
	streamWriteBool(streamId, self.unload);
end;

function AutoLoadWoodToggleEvent:run(connection)
	if not connection:getIsServer() then
		g_server:broadcastEvent(self, false, connection, self.object);
	end;
	if self.object ~= nil then
		self.object:toggleState(self.autoload, self.rightSide, self.unload, true);
	end;
end;

function AutoLoadWoodToggleEvent.sendEvent(vehicle, autoload, rightSide, unload, noEventSend)
	if autoload ~= vehicle.autoload or rightSide ~= vehicle.rightSide or unload ~= vehicle.unload then
		if noEventSend == nil or noEventSend == false then
			if g_server ~= nil then
				g_server:broadcastEvent(AutoLoadWoodToggleEvent:new(vehicle, autoload, rightSide, unload), nil, nil, vehicle);
			else
				g_client:getServerConnection():sendEvent(AutoLoadWoodToggleEvent:new(vehicle, autoload, rightSide, unload));
			end;
		end;
	end;
end;