local metadata = {
"## Interface:FS17 1.3.0.0",
"## Title: AutoLoadWood",
"## Notes: AutoLoadWood",
"## Author: Marhu - fcelsa",
"## Version: 1.0.5",
"## Date: 25/11/2016",
"## Web: http://marhu.net",
"## Web: http://farmingsimulatoritalia.forumcommunity.net"
} 

-- original AutoLoadWood from marhu - based on script version 0.3.0-162 
-- new and fix for FS17 by fcelsa - FSI Modding Team


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:preLoad(savegame)
end;


function AutoLoadWood:load(savegame)

    local xmlFile = self.xmlFile

    self.doCheckSpeedLimit = Utils.overwrittenFunction(self.doCheckSpeedLimit, AutoLoadWood.doCheckSpeedLimit)
    self.dynamicMountTriggerCallback =  Utils.overwrittenFunction(self.dynamicMountTriggerCallback, AutoLoadWood.dynamicMountTriggerCallback)

    self.toggleState = SpecializationUtil.callSpecializationsFunction("toggleState");
    
    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);

        -- <limitToLen   minLen="0.1" maxLen="2.0" delimbOk="0" />
        -- con delimbOk 0 solo i tagli di tronchi completamente puliti dai rami sono caricati!
        local key = "vehicle.AutoLoadWood.limitToLen";
        self.loadMinLen = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#minLen"),0.1);
        self.loadMaxLen = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#maxLen"),60);
        self.loadMaxAtt = Utils.getNoNil(getXMLInt(xmlFile, key .. "#delimbOk"),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)  --original (removed fcelsa)
                    local sizeX, sizeY, sizeZ, numConvexes, numAttachments = getSplitShapeStats(shape)
                    local maxSize = math.max(sizeX, math.max(sizeY, sizeZ)) --fcelsa
                    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)
                    if numAttachments == nil then numAttachments = 0; end;
                    if maxSize <= self.loadMaxLen and maxSize >= self.loadMinLen and numAttachments <= self.loadMaxAtt then
                        removeFromPhysics(shape)
                        setTranslation(shape,dx,dy,dz)
                        setDirection(shape, x, y, z, xdir, ydir, zdir)
                        addToPhysics(shape)
                        self.lastWoodShapes = shape
                    end;
                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;