--
-- HKL
-- Specialization for Hooklift
-- Spezialisierung für Hakenlift
-- @Anpassung  Werkstattleiter
--
-- edit 25/05/2013

HKL = {};

function HKL.prerequisitesPresent(specializations)
    Vehicle.registerJointType("HookJoint");
    print("register joint type: HookJoint");
    return true;
end;

function HKL:load(savegame)

    self.isSelectable = true;
    self.setRpmUp = SpecializationUtil.callSpecializationsFunction("setRpmUp");

    local hydraulicsCount = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.hydraulics#count"), 0);    
    self.hydraulics = {};    
    for i=1, hydraulicsCount do
        local hydraulicName = string.format("vehicle.hydraulics.hydraulic%d", i);        
        self.hydraulics[i] = {};        
        self.hydraulics[i].node = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#index"));
        self.hydraulics[i].punch = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#punch"));
        self.hydraulics[i].translationPunch = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#punchFixpoint"));
        self.hydraulics[i].fixPoint = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#fixpoint"));
        if self.hydraulics[i].punch ~= nil and self.hydraulics[i].translationPunch ~= nil then
            local ax, ay, az = getWorldTranslation(self.hydraulics[i].punch);
            local bx, by, bz = getWorldTranslation(self.hydraulics[i].translationPunch);        
            self.hydraulics[i].punchDistance = Utils.vector3Length(ax-bx, ay-by, az-bz);
        end;
    end;
        
    local tipAnimRootNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.tipAnimation#rootNode"));
    self.tipAnimCharSet = 0;
    if tipAnimRootNode ~= nil and tipAnimRootNode ~= 0 then
        self.tipAnimCharSet = getAnimCharacterSet(tipAnimRootNode);
        if self.tipAnimCharSet ~= 0 then
            local clip = getAnimClipIndex(self.tipAnimCharSet, getXMLString(xmlFile, "vehicle.tipAnimation#clip"));
            assignAnimTrackClip(self.tipAnimCharSet, 0, clip);
            setAnimTrackLoopState(self.tipAnimCharSet, 0, false);
            self.tipAnimSpeedScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.tipAnimation#speedScale"), 1);
            self.tipAnimDuration = getAnimClipDuration(self.tipAnimCharSet, clip);
        end;
    end;
    self.tipReferencePoint = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.tipReferencePoint#index"));
    
    self.attacherJoints[1].jointType = Vehicle.JOINTTYPE_HOOKJOINT;
    self.firstAttachOnLoad = false;
    self.firstAttachTime = 4000;
    self.attachableObject = nil;
    self.isHakenliftTrailer = true;
    self.saveMinRpm = 0;
    
    self.objectTipAnimDuration = nil;
    self.objectTipAnimSpeedScale = nil;
    self.objectTipDischargeEndTime = nil;
    self.objectTipState = nil;
    self.objectTipReferencePoint = nil;
    self.tipState = 0;
    
end;

function HKL:delete()
end;

function HKL:readStream(streamId, connection)

end;

function HKL:writeStream(streamId, connection)

end;

function HKL:mouseEvent(posX, posY, isDown, isUp, button)

end;

function HKL:keyEvent(unicode, sym, modifier, isDown)

end;

function HKL:update(dt)
    
    if self:getIsActiveForInput() then
        local isKeyEvent = false;
        if self.tipState == 0 then
            if InputBinding.isPressed(InputBinding.HKL_DOWN1) and self:getIsActiveForInput() then
                self:setAnimationTime(1, self.animationParts[1].currentPosition+(self.animationParts[1].offSet*(dt/5)));
                isKeyEvent = true;
            elseif InputBinding.isPressed(InputBinding.HKL_UP1) and self:getIsActiveForInput() then
                self:setAnimationTime(1, self.animationParts[1].currentPosition-(self.animationParts[1].offSet*(dt/5)));
                isKeyEvent = true;
            end;
        end;
        self:setRpmUp(dt, isKeyEvent);
    end;
        
    for i, jointDesc in pairs(self.componentJoints) do
    setJointFrame(self.componentJoints[i].jointIndex, 0, self.componentJoints[i].jointNode);
    end;    
    
    setJointFrame(self.attacherJoints[1].jointIndex, 0, self.attacherJoints[1].jointTransform);
    local jointDesc = self.attacherJoints[1];
    local jointLimit1 = (50/2000)*math.max(self.animationParts[1].currentPosition-2750, 0);
    local jointLimit2 = (130/2000)*math.max(self.animationParts[1].currentPosition-2750, 0);
    setJointRotationLimit(jointDesc.jointIndex, 0, true, Utils.degToRad(-0), Utils.degToRad(0));
    setJointRotationLimit(jointDesc.jointIndex, 1, true, Utils.degToRad(-jointLimit1), Utils.degToRad(jointLimit1));
    setJointRotationLimit(jointDesc.jointIndex, 2, true, Utils.degToRad(-jointLimit2), Utils.degToRad(jointLimit2));
    
    for k, implements in pairs(self.attachedImplements) do
        local implement = implements.object;
        if implement.isHakenliftObject then
            if self.animationParts[1].clipStartTime then
                implement.tipReferencePoint = self.tipReferencePoint;
            else
                implement.tipReferencePoint = nil;
            end;
            self.objectTipAnimDuration = implement.tipAnimations[1].animationDuration;
            self.objectTipAnimSpeedScale = implement.tipAnimations[1].animationOpenSpeedScale;
            self.objectTipDischargeEndTime = implement.tipAnimations[1].dischargeEndTime ;
            self.objectTipState = implement.tipState;
            self.tipState = implement.tipState;
        else
            self.objectTipAnimDuration = nil;
            self.objectTipAnimSpeedScale = nil;
            self.objectTipDischargeEndTime = nil;
            self.objectTipState = nil;
        end;
    end;
    if self.objectTipAnimDuration ~= nil and self.objectTipAnimSpeedScale ~= nil and self.objectTipDischargeEndTime ~= nil and self.objectTipState ~= nil then
        local animDuration = self.objectTipAnimDuration;
        local speedScale = self.objectTipAnimSpeedScale;
        self.tipAnimSpeedScale = self.tipAnimDuration/(animDuration/speedScale);
        if self.objectTipState == Trailer.TIPSTATE_CLOSING then
            if self.tipAnimCharSet ~= 0 then
                if getAnimTrackTime(self.tipAnimCharSet, 0) > self.tipAnimDuration then
                    setAnimTrackTime(self.tipAnimCharSet, 0, self.tipAnimDuration);
                end;
                setAnimTrackSpeedScale(self.tipAnimCharSet, 0, -self.tipAnimSpeedScale);
                enableAnimTrack(self.tipAnimCharSet, 0);
            end;
        elseif self.objectTipState == Trailer.TIPSTATE_OPENING then
            if self.tipAnimCharSet ~= 0 then
                if getAnimTrackTime(self.tipAnimCharSet, 0) < 0.0 then
                    setAnimTrackTime(self.tipAnimCharSet, 0, 0.0);
                end;
                setAnimTrackSpeedScale(self.tipAnimCharSet, 0, self.tipAnimSpeedScale);
                enableAnimTrack(self.tipAnimCharSet, 0);
            end;
        elseif self.objectTipState == Trailer.TIPSTATE_CLOSED then
            disableAnimTrack(self.tipAnimCharSet, 0);
        end;
    else
        setAnimTrackTime(self.tipAnimCharSet, 0, getAnimTrackTime(self.tipAnimCharSet, 0));
        setAnimTrackSpeedScale(self.tipAnimCharSet, 0, -self.tipAnimSpeedScale);
        enableAnimTrack(self.tipAnimCharSet, 0);
        if getAnimTrackTime(self.tipAnimCharSet, 0) <= 0.0 then
            disableAnimTrack(self.tipAnimCharSet, 0);
        end;
    end;
        if self.updateSteeringAxleAngle then
        if self.attacherVehicle ~= nil and self.movingDirection < 0 then
            local x,y,z = worldDirectionToLocal(self.steeringAxleNode, localDirectionToWorld(self.attacherVehicle.steeringAxleNode, 0, 0, 1));
            local dot = z;
            dot = dot / Utils.vector2Length(x,z);
            local angle = math.acos(dot);
            if x < 0 then
                angle = -angle;
            end;
            local startSpeed = self.steeringAxleAngleScaleStart;
            local endSpeed = self.steeringAxleAngleScaleEnd;
            local scale = Utils.clamp(1 + (self.lastSpeed*-3600-startSpeed) * 1.0/(startSpeed-endSpeed), 0, 1);
            self.steeringAxleAngle = angle*scale;
        end;
    end;
end;

function HKL:updateTick(dt)

    for i=1, table.getn(self.hydraulics) do
        local ax, ay, az = getWorldTranslation(self.hydraulics[i].node);
        local bx, by, bz = getWorldTranslation(self.hydraulics[i].fixPoint);
        if bx ~= nil and by ~= nil and bz ~= nil then
            local x, y, z = worldDirectionToLocal(getParent(self.hydraulics[i].node), bx-ax, by-ay, bz-az);
            setDirection(self.hydraulics[i].node, x, y, z, 0, 0, 1);
            local distance = Utils.vector3Length(ax-bx, ay-by, az-bz);
            if self.hydraulics[i].punch ~= nil and self.hydraulics[i].punchDistance ~= nil and self.hydraulics[i].translationPunch then
                if self.hydraulics[i].doScale then
                    local xScale, yScale, zScale = getScale(self.hydraulics[i].punch);
                    local newScale = xScale * (distance / self.hydraulics[i].punchDistance);
                    setScale(self.hydraulics[i].punch, 1, 1, newScale);
                else
                    setTranslation(self.hydraulics[i].punch, 0, 0, distance-self.hydraulics[i].punchDistance);
                end;
            end;
        end;
    end;
end;

function HKL:setRpmUp(dt, isActive)
    if self.attacherVehicle ~= nil and self.saveMinRpm ~= 0 then
        if dt ~= nil then
            if isActive == true then
                self.attacherVehicle.motor.minRpm = math.max(self.attacherVehicle.motor.minRpm-dt, -1000);
            else
                self.attacherVehicle.motor.minRpm = math.min(self.attacherVehicle.motor.minRpm+dt*2, self.saveMinRpm);
            end;
        else
            self.attacherVehicle.motor.minRpm = self.saveMinRpm;
        end;
    end;
end;

function HKL:onAttach(attacherVehicle)
    self.attacherVehicle = attacherVehicle;
    if self.attacherVehicleCopy == nil then
        self.attacherVehicleCopy = self.attacherVehicle;
    end;
    self.saveMinRpm = self.attacherVehicle.motor.minRpm;
end;

function HKL:onDetach()
    if self.deactivateOnDetach then
        self:onDeactivate(self);
    else
        self:onDeactivateSounds(self);
    end;
    for k, steerable in pairs(g_currentMission.steerables) do
        if self.attacherVehicleCopy == steerable then
            steerable.motor.minRpm = self.saveMinRpm;
            self.attacherVehicleCopy = nil;
        end;
    end;
end;

function HKL:draw()
    
    if self.animationParts[1].clip then
            g_currentMission:addHelpButtonText(string.format(g_i18n:getText("HKL_UP1")), InputBinding.HKL_UP1);
            g_currentMission:addHelpButtonText(string.format(g_i18n:getText("HKL_DOWN1")), InputBinding.HKL_DOWN1);
    end;
    
end;

function HKL:validateAttacherJoint(HookJoint, jointDesc, dt)
    return true;
end;