--
-- Grubber
-- Class for all Grubbers
--
-- @author  Stefan Geiger (mailto:sgeiger@giants.ch)
-- @modified Denis Greßhöner (Acid_Burn84@gmx.de)
-- @date  20/05/08

Grubber = {};

function Grubber:new(configFile, positionX, offsetY, positionZ, rotationY, customMt)

    if Grubber_mt == nil then
        Grubber_mt = Class(Grubber, Implement);
    end;

    local mt = customMt;
    if mt == nil then
        mt = Grubber_mt;
    end;
    local instance = Implement:new(configFile, positionX, offsetY, positionZ, rotationY, mt);

    local xmlFile = loadXMLFile("TempConfig", configFile);
	instance.drumNodeMain = Utils.indexToObject(instance.rootNode, getXMLString(xmlFile, "vehicle.drum#index1"));
	instance.drumNodeRight = Utils.indexToObject(instance.rootNode, getXMLString(xmlFile, "vehicle.drum#index2"));
    instance.drumNodeLeft = Utils.indexToObject(instance.rootNode, getXMLString(xmlFile, "vehicle.drum#index3"));
    instance.drumRotationScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.drum#rotationScale"), 1);

    local rotationPartNodeRight = Utils.indexToObject(instance.rootNode, getXMLString(xmlFile, "vehicle.rotationPartRight#index"));
    if rotationPartNodeRight ~= nil then
        instance.rotationPartRight = {};
        instance.rotationPartRight.node = rotationPartNodeRight;

        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.rotationPartRight#minRot"));
        instance.rotationPartRight.minRot = {};
        instance.rotationPartRight.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        instance.rotationPartRight.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        instance.rotationPartRight.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.rotationPartRight#maxRot"));
        instance.rotationPartRight.maxRot = {};
        instance.rotationPartRight.maxRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        instance.rotationPartRight.maxRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        instance.rotationPartRight.maxRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        instance.rotationPartRight.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.rotationPartRight#rotTime"), 2)*1000;
        instance.rotationPartRight.touchRotLimit = Utils.degToRad(Utils.getNoNil(getXMLString(xmlFile, "vehicle.rotationPartRight#touchRotLimit"), 10));
    end;

    local rotationPartNodeLeft = Utils.indexToObject(instance.rootNode, getXMLString(xmlFile, "vehicle.rotationPartLeft#index"));
    if rotationPartNodeLeft ~= nil then
        instance.rotationPartLeft = {};
        instance.rotationPartLeft.node = rotationPartNodeLeft;

        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.rotationPartLeft#minRot"));
        instance.rotationPartLeft.minRot = {};
        instance.rotationPartLeft.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        instance.rotationPartLeft.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        instance.rotationPartLeft.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.rotationPartLeft#maxRot"));
        instance.rotationPartLeft.maxRot = {};
        instance.rotationPartLeft.maxRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        instance.rotationPartLeft.maxRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        instance.rotationPartLeft.maxRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        instance.rotationPartLeft.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.rotationPartLeft#rotTime"), 2)*1000;
        instance.rotationPartLeft.touchRotLimit = Utils.degToRad(Utils.getNoNil(getXMLString(xmlFile, "vehicle.rotationPartLeft#touchRotLimit"), 10));
    end;
    delete(xmlFile);

    instance.hasGroundContact = false;
    instance.isExpandedRight = false;
    instance.isExpandedLeft = false;
    instance.rotationMaxRight = true;
    instance.rotationMaxLeft = true;
    instance.speedViolationMaxTime = 2500;
    instance.speedViolationTimer = instance.speedViolationMaxTime;

    instance.stopDelayMain = 0;
    instance.stopDelayRight = 0;
    instance.stopDelayLeft = 0;

    return instance;
end;

function Grubber:delete()
    removeContactReport(self.rootNode);
    Implement.delete(self);
end;

function Grubber:mouseEvent(posX, posY, isDown, isUp, button)
    Implement.mouseEvent(self, posX, posY, isDown, isUp, button);
end;

function Grubber:keyEvent(unicode, sym, modifier, isDown)
    Implement.keyEvent(self, unicode, sym, modifier, isDown);
end;

function Grubber:update(dt)
    if self.isAttached and self.isSelected then
        if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA) then
            self.rotationMaxRight = not self.rotationMaxRight;
            self.rotationMaxLeft = not self.rotationMaxLeft;
        end;
    end;

    if self.isAttached then
        self.isExpandedRight = false;
        if self.rotationPartRight ~= nil then
            local x, y, z = getRotation(self.rotationPartRight.node);
            local minRot = self.rotationPartRight.minRot;
            local eps = self.rotationPartRight.touchRotLimit;

            if math.abs(x-minRot[1]) < eps and math.abs(y-minRot[2]) < eps and math.abs(z-minRot[3]) < eps then
                self.isExpandedRight = true;
            end;
        end;

        self.isExpandedLeft = false;
        if self.rotationPartLeft ~= nil then
            local x, y, z = getRotation(self.rotationPartLeft.node);
            local minRot = self.rotationPartLeft.minRot;
            local eps = self.rotationPartLeft.touchRotLimit;

            if math.abs(x-minRot[1]) < eps and math.abs(y-minRot[2]) < eps and math.abs(z-minRot[3]) < eps then
                self.isExpandedLeft = true;
            end;
        end;

        if self.hasGroundContact then
            self.stopDelayMain = 30;
        end;
        if self.stopDelayMain > 0 and self.drumNodeMain ~= nil then
            rotate(self.drumNodeMain, self.drumRotationScale * self.attacherVehicle.lastSpeed * self.attacherVehicle.movingDirection, 0, 0);  
        end;
        if not self.hasGroundContact and self.stopDelayMain >= 0 then
            self.stopDelayMain = self.stopDelayMain -1;
        end;

        if self.hasGroundContact and self.isExpandedRight then
            self.stopDelayRight = 30;
        end;
        if self.stopDelayRight > 0 and self.drumNodeRight ~= nil then
			rotate(self.drumNodeRight, self.drumRotationScale * self.attacherVehicle.lastSpeed * self.attacherVehicle.movingDirection, 0, 0);  
		end;
        if (not self.hasGroundContact or not self.isExpandedRight) and self.stopDelayRight >= 0 then
            self.stopDelayRight = self.stopDelayRight -1;
        end;

        if self.hasGroundContact and self.isExpandedLeft then
            self.stopDelayLeft = 30;
        end;
        if self.stopDelayLeft > 0 and self.drumNodeLeft ~= nil then
			rotate(self.drumNodeLeft, self.drumRotationScale * self.attacherVehicle.lastSpeed * self.attacherVehicle.movingDirection, 0, 0);  
		end;
        if (not self.hasGroundContact or not self.isExpandedLeft) and self.stopDelayLeft >= 0 then
            self.stopDelayLeft = self.stopDelayLeft -1;
        end;
        
        if self.hasGroundContact and table.getn(self.cuttingAreas) > 0 then
            local x,y,z = getWorldTranslation(self.cuttingAreas[1].start);
            local x1,y1,z1 = getWorldTranslation(self.cuttingAreas[1].width);
            local x2,y2,z2 = getWorldTranslation(self.cuttingAreas[1].height);
            Utils.updateCultivatorArea(x, z, x1, z1, x2, z2);
        end;

        if self.hasGroundContact and self.isExpandedRight and table.getn(self.cuttingAreas) > 1 then
            x,y,z = getWorldTranslation(self.cuttingAreas[2].start);
            x1,y1,z1 = getWorldTranslation(self.cuttingAreas[2].width);
            x2,y2,z2 = getWorldTranslation(self.cuttingAreas[2].height);
            Utils.updateCultivatorArea(x, z, x1, z1, x2, z2);
        end;

        if self.hasGroundContact and self.isExpandedLeft and table.getn(self.cuttingAreas) > 2 then
            x,y,z = getWorldTranslation(self.cuttingAreas[3].start);
            x1,y1,z1 = getWorldTranslation(self.cuttingAreas[3].width);
            x2,y2,z2 = getWorldTranslation(self.cuttingAreas[3].height);
            Utils.updateCultivatorArea(x, z, x1, z1, x2, z2);
        end;
    end;

    if self.isAttached and self.hasGroundContact then
        if self.attacherVehicle.lastSpeed*3600 > 20 then
            self.speedViolationTimer = self.speedViolationTimer - dt;
            if self.speedViolationTimer < 0 then
                self.attacherVehicle:detachImplementByObject(self);
            end;
        else
            self.speedViolationTimer = self.speedViolationMaxTime;
        end;
    else
        self.speedViolationTimer = self.speedViolationMaxTime;
    end;

    if self.rotationPartRight ~= nil then
        local x, y, z = getRotation(self.rotationPartRight.node);
        local rot = {x,y,z};
        local newRot = Utils.getMovedLimitedValues(rot, self.rotationPartRight.maxRot, self.rotationPartRight.minRot, 3, self.rotationPartRight.rotTime, dt, not self.rotationMaxRight);
        setRotation(self.rotationPartRight.node, unpack(newRot));
    end;

    if self.rotationPartLeft ~= nil then
        local x, y, z = getRotation(self.rotationPartLeft.node);
        local rot = {x,y,z};
        local newRot = Utils.getMovedLimitedValues(rot, self.rotationPartLeft.maxRot, self.rotationPartLeft.minRot, 3, self.rotationPartLeft.rotTime, dt, not self.rotationMaxLeft);
        setRotation(self.rotationPartLeft.node, unpack(newRot));
    end;

    Implement.update(self, dt);
end;

function Grubber:draw()
    Implement.draw(self);
 
    if self.isExpandedRight or self.isExpandedLeft then
        g_currentMission:addHelpButtonText("Grubber einklappen", InputBinding.IMPLEMENT_EXTRA);
    else
        g_currentMission:addHelpButtonText("Grubber ausklappen", InputBinding.IMPLEMENT_EXTRA);
    end;

    if math.abs(self.speedViolationTimer - self.speedViolationMaxTime) > 2 then
        g_currentMission:addWarning("Fahren Sie nicht zu schnell\nTempomat Stufe 1: Taste 1", 0.07+0.022, 0.019+0.029);
    end;
end;

function Grubber:onAttach(attacherVehicle)
    Implement.onAttach(self, attacherVehicle);

    addContactReport(self.rootNode, "groundContactReport", self);
end;

function Grubber:onDetach()
    Implement.onDetach(self);

    self.speedViolationTimer = self.speedViolationMaxTime;

    removeContactReport(self.rootNode);
end;

function Grubber:groundContactReport(objectId, otherObjectId, isStart, normalForce, tangentialForce)
    if otherObjectId == g_currentMission.terrainRootNode then
        self.hasGroundContact = normalForce > 0 or tangentialForce > 0;
    end;
end;
