-- 
-- FSM Iveco Stralis Functions + Clixtar
-- version: 1.2
-- date: 13.10.2015
-- last update: 28.02.2016
-- author: [FSM]Chefkoch
-- hp: http://fsm-team.de
-- 
-- Keine Veränderung ohne meine Erlaubnis!
-- No modification without    my permission!
-- 
-- used sources:
-- *cablight Script LS13 - author:? | <cablight realLight="0>0" corona="0>0|1" />
-- *hudLoad Script LS15 - author:? | <onBoardHud screen1Index="0>32|0" screen2Index="0>32|1" screen3Index="0>32|2" screen4Index="0>32|2" />
-- *handBrake Script - author: webby
-- *added hazzard light support for cab

stralisClixtar = {};
stralisClixtar.modDir = g_currentModDirectory;

function stralisClixtar.prerequisitesPresent(specializations) 
    Vehicle.registerJointType("clixtar");
    return SpecializationUtil.hasSpecialization(Motorized, specializations); 
end;

function stralisClixtar:load(savegame)
    -- onBoard Display Stuff
    self.speedWaitingMaxTimeHud = 6000; 
    self.speedWaitingTimerHud = 1; 
    self.hudFirst  = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.Stralis.onBoardHud#screen1Index"));
    self.hudSecond = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.Stralis.onBoardHud#screen2Index"));
    self.hudThird  = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.Stralis.onBoardHud#screen3Index"));
    self.hudFour  = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.Stralis.onBoardHud#screen4Index"));
    
    -- Cablight Stuff
    self.setCablight = SpecializationUtil.callSpecializationsFunction("setCablight");
    self.cl = {};
    self.cl.rl = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.Stralis.cablight#realLight"));
    self.cl.co = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.Stralis.cablight#corona"));
    self.cl.turnOn = false;
    self.cl.isOn = false;
    self.cl.active = false;
    setVisibility( self.cl.rl, false );
    setVisibility( self.cl.co, false );
    
    CablightSoundFile = Utils.getFilename("Sounds/blinktick.wav", self.baseDirectory);
    self.CablightSoundId = createSample("CablightSound");
    loadSample(self.CablightSoundId, CablightSoundFile, false);
    self.CablightSoundPlaying = false;
    
    -- Warnblinker
    self.warnBlinkLight = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.stralis.WarnBlinkLicht#index"));
    setVisibility(self.warnBlinkLight, false);
    
    -- Tankleuchte
    self.tankLeuchte = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.Stralis.TankLeuchte#index"));
    self.tankMinWarnLevel = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.Stralis.TankLeuchte#minWarnLevel"));
    setVisibility(self.tankLeuchte, false);
    
    -- Ladekontrollleuchte
    self.ladeLeuchte = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.Stralis.LadeKontrollLeuchte#index"));
    setVisibility(self.ladeLeuchte, false);
    self.ladeLeuchteOn = 1;
    self.ladeTimer = 10;
    
    -- Temperaturzeiger Wasser
    self.temperaturZeiger = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.Stralis.TemperaturZeiger#zeigerIndex"));
    self.temperaturZeigerMaxRot = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.Stralis.TemperaturZeiger#maxRotation"));
    self.tempCnt = 0;

    self.Object = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.Stralis.Axle#index"));
    setVisibility(self.Object, false);
    
    -- Parkbrake Stuff
    if self.setparkingBrakeStateHM ~= nil then
        return;
    end;
    
    self.ParkBrakeOnHud = Overlay:new("hBOn", (stralisClixtar.modDir.."Schema/Park_symbol.dds"), 0.97, 0.172, 0.0225, 0.039);
    
    self.setParkBrakeState = SpecializationUtil.callSpecializationsFunction("setParkBrakeState");

    self.ParkBrake = true;

    ParkBrakeSoundFile = Utils.getFilename("Sounds/Handbrake_on.wav", self.baseDirectory);
    self.ParkBrakeSoundId = createSample("ParkBrakeSound");
    loadSample(self.ParkBrakeSoundId, ParkBrakeSoundFile, false);
    self.ParkBrakePlaying = false;

    self.ParkBrakeReleasePlaying = false;
    brakereleaseSoundFile = Utils.getFilename("Sounds/Handbrake_release.wav", self.baseDirectory);
    self.ParkBrakeReleaseSoundId = createSample("brakereleaseSound");
    loadSample(self.ParkBrakeReleaseSoundId, brakereleaseSoundFile, false);

    self.ParkBrakeReleasePlaying = false;
    self.BreakForceVal = 10000/self.motor.brakeForce;
    if g_currentMission.extraHudMode == nil then
        g_currentMission.extraHudMode = 0;
    end;

    self.stickNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.Stralis.brakeStick#index"));
    self.brakeIn = getXMLFloat(xmlFile, "vehicle.Stralis.brakeStick#brakeIn");
    self.brakeOut = getXMLFloat(xmlFile, "vehicle.Stralis.brakeStick#brakeOut");
    
    self.ParkBrakeTurnOff = false;
    
    -- Joystick Stuff
    self.sj = {};
    self.sj.node = Utils.indexToObject( self.components, getXMLString(xmlFile, "vehicle.Stralis.gearStick#node") );
    self.sj.rotF = math.rad( getXMLFloat(xmlFile, "vehicle.Stralis.gearStick#rotFront") );
    self.sj.rotB = math.rad( getXMLFloat(xmlFile, "vehicle.Stralis.gearStick#rotBack") );
    self.sj.rotT = 0;
    self.sj.rotC = 0;
    
    self.forceJoystick_time = 0;
end;

function stralisClixtar:delete() 
end;

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

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

function stralisClixtar:update(dt) 

    if self.isMotorStarted then 
        if self.speedWaitingTimerHud < self.speedWaitingMaxTimeHud then 
            setVisibility(self.hudFirst, true);
            setVisibility(self.hudSecond, false);
            setVisibility(self.hudThird, false);
            setVisibility(self.hudFour, false); 
        end;
        
        if self.speedWaitingTimerHud > 2000 then 
            setVisibility(self.hudFirst, false);
            setVisibility(self.hudSecond, true);
            setVisibility(self.hudThird, false);
            setVisibility(self.hudFour, false); 
        end;
        
        if self.speedWaitingTimerHud > 4000 then
            setVisibility(self.hudFirst, false);
            setVisibility(self.hudSecond, false);
            setVisibility(self.hudThird, true);
            setVisibility(self.hudFour, false); 
        end;
        
        if self.speedWaitingTimerHud > 5999 then 
            setVisibility(self.hudFirst, false);
            setVisibility(self.hudSecond, false);
            setVisibility(self.hudThird, false);
            setVisibility(self.hudFour, true); 
        end;
        
        self.speedWaitingTimerHud = self.speedWaitingTimerHud + dt;
    else
        self.speedWaitingTimerHud = 1;
        setVisibility(self.hudFirst, false);
        setVisibility(self.hudSecond, false);
        setVisibility(self.hudThird, false);
        setVisibility(self.hudFour, false); 
    end;
    
    
    if self:getIsActive() then
        
        -- WarnBlinkLicht
        if self.turnSignalState == Vehicle.TURNSIGNAL_HAZARD then
                setVisibility(self.warnBlinkLight, true);
            else
                setVisibility(self.warnBlinkLight, false);
        end;
    
        if self.isMotorStarted then
            if self.ladeLeuchteOn == 1 then
                setVisibility(self.ladeLeuchte, true);
                if self.movingDirection ~= 0 then
                    self.timerTrue = true;
                end;
                if self.timerTrue then
                    self.ladeTimer = math.max(self.ladeTimer - 0.1, 0);
                end;
                if self.ladeTimer == 0 then
                    setVisibility(self.ladeLeuchte, false);
                    self.timerTrue = nil;
                    self.ladeLeuchteOn = 0;
                    self.ladeTimer = 10;
                end;
            end;

            local actualTankInhalt = 0;
            if self.fuelCapacity > 0 then
                actualTankInhalt = (self.fuelFillLevel / self.fuelCapacity + 0.0001) * 100;
            end;
            if actualTankInhalt < self.tankMinWarnLevel then
                setVisibility(self.tankLeuchte, true);
            else
                setVisibility(self.tankLeuchte, false);
            end;
            if self.tempCnt < 3000 then
                setRotation(self.temperaturZeiger, 0, 0, Utils.degToRad(-(self.temperaturZeigerMaxRot/10000)*self.tempCnt));
                self.tempCnt = self.tempCnt + 0.8;
            elseif self.tempCnt > 3000 and self.tempCnt < 6000 then
                setRotation(self.temperaturZeiger, 0, 0, Utils.degToRad(-(self.temperaturZeigerMaxRot/10000)*self.tempCnt));
                self.tempCnt = math.min(self.tempCnt + 0.3, 10000);            
            else
                setRotation(self.temperaturZeiger, 0, 0, Utils.degToRad(-(self.temperaturZeigerMaxRot/10000)*self.tempCnt));
                self.tempCnt = math.min(self.tempCnt + 0.04, 10000);
            end;
            else
            self.tempCnt = math.max(self.tempCnt - 0.1, 0);
        end;
    end;

    if self:getIsActive() then
        if self.isClient and self:getIsActiveForInput(false) and not self:hasInputConflictWithSelection() then
            if InputBinding.hasEvent(InputBinding.CABLIGHT) then
                self:setCablight(not self.cl.turnOn);
                playSample(self.CablightSoundId,1,0.5,0);
            end;
        end;
    end;
    
    local realLightsActive = false;
    realLightsActive = self:getIsActiveForLights();
    
    if (self.cl.turnOn == true and self.cl.isOn == false) or (self.cl.active ~= realLightsActive) then
        if self.cl.rl ~= nil then
            if realLightsActive then
                setVisibility( self.cl.rl, true );
            else
                setVisibility( self.cl.rl, false );
            end
        end;
        if self.cl.co ~= nil then
            setVisibility( self.cl.co, true );            
        end;
        self.cl.active = realLightsActive;
        self.cl.isOn = true;
    elseif (self.cl.turnOn == false and self.cl.isOn == true) then
        if self.cl.rl ~= nil then
            setVisibility( self.cl.rl, false );
        end;
        if self.cl.be ~= nil then
            setVisibility( self.cl.be, false );
        end;
        if self.cl.co ~= nil then
            setVisibility( self.cl.co, false );        
        end;
        self.cl.isOn = false;
    end;
    
    -- Brake Stuff
    if self.setParkBrakeStateHM ~= nil then
        return;
    end;
    if self.isClient then
        if self:getIsActiveForInput() or self:getIsActiveForInput(false) then
            if InputBinding.hasEvent(InputBinding.handbremse) then
                self:setParkBrakeState(not self.ParkBrake);
                
                if self.ParkBrake and self:getIsActiveForSound() and self.isClient then
                    playSample(self.ParkBrakeSoundId,1,1,0);
                    setRotation(self.stickNode, (self.brakeIn),0, 0);
                else
                    playSample(self.ParkBrakeReleaseSoundId,1,1,0);
                    setRotation(self.stickNode, (self.brakeOut),0, 0);
                end;
            end;
        end;
        local ax = false;
        if self.axisForward ~= nil then
            if self.axisForward ~= 0 then
                if self.axisForward < -0.2 then
                    ax = true;
                end;
            end;
        end;
        if Input.isKeyPressed(Input.KEY_s) or ax == true then
            if not self.braking then
                self.braking = true;
            end;
            if not self.ParkBrakePlaying and self:getIsActiveForSound() then
                self.ParkBrakePlaying = true;
            end;
            self.ParkBrakeReleasePlaying = false;
        else
            self.ParkBrakePlaying = false;
            self.braking = false;
            if not self.ParkBrakeReleasePlaying and self:getIsActiveForSound() then
                self.ParkBrakeReleasePlaying = true;
            end;
        end;
    end;
    
    -- Joystick
    
    if self:getIsActive() then
        if self.isClient then
            
            local axisForward = 0;
            axisForward = InputBinding.getDigitalInputAxis(InputBinding.AXIS_MOVE_FORWARD_VEHICLE);
            if InputBinding.isAxisZero(axisForward) then
                axisForward = InputBinding.getAnalogInputAxis(InputBinding.AXIS_MOVE_FORWARD_VEHICLE)
            end;
            if axisForward < 0 then
                self.sj.rotT = -self.sj.rotF*axisForward;
            elseif axisForward > 0 then
                self.sj.rotT = self.sj.rotB*axisForward;
            else
                self.sj.rotT = 0;
            end
            
            if not self.isRealistic then 
                if self.ESLimiter ~= nil and self.lastLevel ~= 0 and self:getIsActiveForInput(false) and not self:hasInputConflictWithSelection() then
                    local percentage = self.ESLimiter.percentage;
                    if InputBinding.isPressed(InputBinding.ESLimiter_PLUS) and percentage[self.lastLevel] < 100 then                    
                        self.sj.rotT = self.sj.rotF/2;
                    elseif InputBinding.isPressed(InputBinding.ESLimiter_MINUS) and percentage[self.lastLevel] > 10 then
                        self.sj.rotT = self.sj.rotB/2;
                    end;
                end;    
            else
                
            end;

            if self.forceJoystick_time > self.time then
                if self.forceJoystick == true then
                    self.sj.rotT = self.sj.rotF/2;
                else
                    self.sj.rotT = self.sj.rotB/2;
                end;
            end;
            
            
            if self.sj.rotC < self.sj.rotT then
                self.sj.rotC = self.sj.rotC + dt/1000;
                if self.sj.rotC > self.sj.rotT then
                    self.sj.rotC = self.sj.rotT;
                end;
            elseif self.sj.rotC > self.sj.rotT then
                self.sj.rotC = self.sj.rotC - dt/1000;
                if self.sj.rotC < self.sj.rotT then
                    self.sj.rotC = self.sj.rotT;
                end;
            end;
            
            setRotation( self.sj.node, self.sj.rotC, 0, 0 );
            
        end;
    end;

    if self.motor.speedLevel ~= 0 then
    end;
end;

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

function stralisClixtar:getSaveAttributesAndNodes(nodeIdent) 
end;

function stralisClixtar:readStream(streamId, connection)
    local state = streamReadBool(streamId);
    self:setCablight(state, true);
    
    if self.setParkBrakeStateHM ~= nil then
        return;
    end;
    self:setParkBrakeState(streamReadBool(streamId));
end;

function stralisClixtar:writeStream(streamId, connection)
    streamWriteBool(streamId, self.cl.turnOn);
    
    if self.setParkBrakeStateHM ~= nil then
        return;
    end;
    streamWriteBool(streamId, self.ParkBrake);
end;

function stralisClixtar:updateTick(dt)
    if self.setParkBrakeStateHM ~= nil then
        return;
    end;
    if self.isServer then
        if self.ParkBrake then
            for k,wheel in pairs(self.wheels) do
                wheel.hasHandbrake = true;
                if self.isRealistic then
                    WheelsUtil.updateWheelsPhysics(self, 0, self.lastSpeed, 0, true, 0, true)
                else
                    WheelsUtil.updateWheelsPhysics(self, 0, self.lastSpeed, 0, true, 0)
                end;
                setWheelShapeProps(wheel.node, wheel.wheelShape, 0, 999, wheel.steeringAngle);
            end;
        elseif (not self.ParkBrake) and self.ParkBrakeTurnOff then
            for k,wheel in pairs(self.wheels) do
                setWheelShapeProps(wheel.node, wheel.wheelShape, 0, 0, wheel.steeringAngle);
            end;
            self.ParkBrakeTurnOff = false;
        end;
    end;
end;

function stralisClixtar:draw()
    if g_currentMission.controlledVehicle ~= nil then
        g_currentMission:addHelpButtonText(g_i18n:getText("CABLIGHTONOFF"), InputBinding.CABLIGHT);
    end;
    
    -- Brake Stuff
    if self.setParkBrakeStateHM ~= nil then
        return;
    end;
    if self.isEntered then
        if self.ParkBrake then
            g_currentMission:addHelpButtonText(g_i18n:getText("handbrakeOFF"), InputBinding.handbremse);
            self.ParkBrakeOnHud:render();
            if self.isMotorStarted then
                local ax = false;
                if self.axisForward ~= nil then
                    if self.axisForward < -0.4 then
                        ax = true;
                    end;
                end;
                if Input.isKeyPressed(Input.KEY_w) or ax == true then
                    g_currentMission:addWarning(g_i18n:getText("handbrakeRELEASE"), 0.015, 0.030);
                end;
            end;
        else
            g_currentMission:addHelpButtonText(g_i18n:getText("handbrakeON"), InputBinding.handbremse);
        end;
    end;
    
end;

function stralisClixtar:attachImplement()
    for k,v in pairs(self.attachedImplements) do
        if v.object.attacherVehicle ~= nil then
            if v.object.attacherVehicle.attacherJoints[v.jointDescIndex] == self.attacherJoints[1] then
                setVisibility(self.Object, true);
            end;
        end;
    end;
end;

function stralisClixtar:detachImplement()
    setVisibility(self.Object, false);
end;

function stralisClixtar:setCablight(state, noEventSend)
    SetCablightEvent.sendEvent(self, state, noEventSend);
    self.cl.turnOn = state;
end;

function stralisClixtar:setParkBrakeState(state, noEventSend)
    if self.setParkBrakeStateHM ~= nil then
        return;
    end;
    ParkBrakeEvent.sendEvent(self, state, noEventSend);
    self.ParkBrake = state;
    if state then
        self.ParkBrakeTurnOff = state;
    end;
    if self.ParkBrakelight ~= nil then
        setVisibility(self.ParkBrakelight, state);
    end;
end;

function stralisClixtar:realSetSpeedLimiterValue(increase)
    if increase then
        self.forceJoystick = true;
    else
        self.forceJoystick = false;
    end;    
    self.forceJoystick_time = self.time + 100;
end;

--
-- iNet Stuff
--
SetCablightEvent = {};
SetCablightEvent_mt = Class(SetCablightEvent, Event);

ParkBrakeEvent = {};
ParkBrakeEvent_mt = Class(ParkBrakeEvent, Event);

InitEventClass(SetCablightEvent, "SetCablightEvent");
InitEventClass(ParkBrakeEvent, "ParkBrakeEvent");

function SetCablightEvent:emptyNew()
    local self = Event:new(SetCablightEvent_mt);
    self.className="SetCablightEvent";
    return self;
end;

function ParkBrakeEvent:emptyNew()
    local self = Event:new(ParkBrakeEvent_mt);
    self.className="ParkBrakeEvent";
    return self;
end;

function SetCablightEvent:new(object, state)
    local self = SetCablightEvent:emptyNew()
    self.object = object;
    self.state = state;
    return self;
end;

function ParkBrakeEvent:new(vehicle, ParkBrake)
    local self = ParkBrakeEvent:emptyNew()
    self.vehicle = vehicle;
    self.ParkBrake = ParkBrake;
    return self;
end;

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

function ParkBrakeEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
    self.ParkBrake = streamReadBool(streamId);
    self.vehicle = networkGetObject(id);
    self:run(connection);
end;

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

function ParkBrakeEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));
    streamWriteBool(streamId, self.ParkBrake);
end;

function SetCablightEvent:run(connection)
    self.object:setCablight(self.state, true);
    if not connection:getIsServer() then
        g_server:broadcastEvent(SetCablightEvent:new(self.object, self.state), nil, connection, self.object);
    end;
end;

function ParkBrakeEvent:run(connection)
    if self.vehicle ~= nil then
        if not connection:getIsServer() then
            g_server:broadcastEvent(ParkBrakeEvent:new(self.vehicle, self.ParkBrake), nil, connection, self.vehicle);
        end;
        if self.vehicle.setParkBrakeState ~= nil then
            self.vehicle:setParkBrakeState(self.ParkBrake, true);
        end;
    end;
end;

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

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

