--
-- BJR_ManualIgnition
-- Specialization for manual motor ignition
--
-- @v1: Templaer - 01 May   2009
-- @v2: Henly20  - 24 April 2012
--
-- @author:        Xentro (www.ls-uk.info)(Marcus@Xentro.se)
-- @version:    v2.0
-- @date:       2012-10-26
-- @history:    v1.0 - inital implementation
--                v1.1 - 28/10/12 - Changed in to non-global class - JoXXer (BJR-Modding)
--                v1.1.2 - 01/11/12 - Added valuable changes from MI 3.0.1 - JoXXer (BJR-Modding)
--                v2.0 - 05/09/13 - Adjusted to work with moreRealistic with changes from dural - JoXXer (BJR-Modding)
--
--
--

BJR_ManualIgnition = {};

function BJR_ManualIgnition.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(Motorized, specializations);
end;

function BJR_ManualIgnition:load(savegame)
    self.setManualIgnitionMode = SpecializationUtil.callSpecializationsFunction("setManualIgnitionMode");
    self.overrideIgnitionInput = false;
    
    if self.motorStopSound ~= nil then
        self.motorStopSoundNew = self.motorStopSound;
        self.motorStopSoundVolumeNew = self.motorStopSoundVolume;
    elseif self.mrMotorStopSound ~= nil then -- support for mrIndoorSound
        self.motorStopSoundNew = self.mrMotorStopSound;
        self.motorStopSoundVolumeNew = self.mrMotorStopSoundVolume;
    end;
    
    self.playedMotorStopSoundNew = true;
    self.ignitionKey = false;
    self.allowedIgnition = false;
    self.isMotorStarted = false;
    self.overrideHud = false;
    
    self.motorStopSoundVolume = 0;
    self.ignitionMode = 0;

    self.dashLights = {};
    self.dashLights.activated = false;
    self.dashLights.table = {};
    local i = 0;
    while true do
        local key = string.format("vehicle.dashLights.dashLight(%d)", i);
        if not hasXMLProperty(xmlFile, key) then break; end;
        
        local index = getXMLString(xmlFile, key .. "#index")
        if index ~= nil then
            table.insert(self.dashLights.table, {node = Utils.indexToObject(self.components, index)});
            i = i + 1;
        end;        
    end;
    
    local keyPath = "vehicle.key";
    self.key = {};
    self.key.mode = 0;
    self.key.lastMode = 0;
    if hasXMLProperty(xmlFile, keyPath) then
        local index = getXMLString(xmlFile, keyPath .. "#index")
        if index ~= nil then
            self.key.node = Utils.indexToObject(self.components, index);
            
            local off = Utils.getRadiansFromString(getXMLString(xmlFile, keyPath .. "#off"), 3);
            local on = Utils.getRadiansFromString(getXMLString(xmlFile, keyPath .. "#on"), 3);
            local start = Utils.getRadiansFromString(getXMLString(xmlFile, keyPath .. "#start"), 3);
            
            if off == nil then
                local x, y, z = getRotation(self.key.node);
                off = {x, y, z};
            end;
            
            if on ~= nil and start ~= nil then
                self.key.rot = {};
                self.key.rot['off'] = off;
                self.key.rot['on'] = on;
                self.key.rot['start'] = start;
            else
                print('Error: <key> is missing a value for on="x y z" or starting="x y z" in ' .. self.configFileName);
            end;
        end;
    end;

    self.idleFuelUsage = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.fuelUsage#idleFuelUsage"), 10) / 100;
    
    self.mpwt = 0;
    self.mpwtm = "";
    
    self:addConflictCheckedInput(InputBinding.MANUAL_IGNITION_KEY);
end;

function BJR_ManualIgnition:delete()
end;

function BJR_ManualIgnition:readStream(streamId, connection)
    self:setManualIgnitionMode(streamReadInt8(streamId), true);
end;

function BJR_ManualIgnition:writeStream(streamId, connection)
    streamWriteInt8(streamId, self.ignitionMode);
end;

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

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

function BJR_ManualIgnition:update(dt)
    if self:getIsActive() and self:getIsActiveForInput(false) and self.isClient and not self.overrideIgnitionInput and not self:hasInputConflictWithSelection() then
        if InputBinding.hasEvent(InputBinding.MANUAL_IGNITION_KEY) then
            if self.ignitionMode > 2 then
                self.ignitionMode = 0;
            end;
            if self.ignitionMode ~= 1 or self.ignitionMode == 1 then
                self:setManualIgnitionMode(math.abs(self.ignitionMode + 1));
            end;
        end;
        
        if InputBinding.isPressed(InputBinding.MANUAL_IGNITION_KEY) and self.ignitionMode == 2 then
            self.key.mode = 2;
        else        
            if self.isMotorStarted then
                self.key.mode = 1;
            end;
        end;
        
        if (self.axisForward < -0.5 or self.axisForward > 0.5) and self.ignitionMode == 0 then
            self.mpwt = self.time + 800;
            self.mpwtm = string.format(g_i18n:getText("MANUAL_IGNITION_ERROR"), self.typeDesc);
        end;
    end;
 end;

function BJR_ManualIgnition:updateTick(dt)
if self:getIsActive() then
        local key = self.key;
        if key.mode ~= key.lastMode then
            if key.rot ~= nil then
                if key.mode == 1 then
                    setRotation(key.node, unpack(key.rot['on']));
                elseif key.mode == 2 then
                    setRotation(key.node, unpack(key.rot['start']));
                else
                    setRotation(key.node, unpack(key.rot['off']));
                end;
            end;
            key.lastMode = key.mode;
        end;
    end;
    
    
    local stopAI = false;
    if not self:getIsHired() then
        if self.ignitionKey and self.allowedIgnition then
            self:startMotor(true);
            self.deactivateOnLeave = false;
            Utils.setEmittingState(self.exhaustParticleSystems, true)
            self.allowedIgnition = false;
        elseif not self.ignitionKey and self.allowedIgnition then
            self:stopMotor(true);
            self.deactivateOnLeave = true;
            self.allowedIgnition = false;
        elseif self.ignitionKey and not self.allowedIgnition and self.deactivateOnLeave then
            self.deactivateOnLeave = false;
        end;

        if not self.playedMotorStopSoundNew and self.motorStopSoundNew ~= nil then
            playSample(self.motorStopSoundNew, 1, self.motorStopSoundVolumeNew, 0);
            self.playedMotorStopSoundNew = true;
        end;
    elseif not self.ignitionKey and not self.deactivateOnLeave then
        stopAI = true;
    end;
    
    if self.ignitionMode ~= 2 or self.motorStartTime > self.time and self.ignitionMode == 2 then
        local stop = false;
        
        for _, implement in pairs(self.attachedImplements) do
            local tool = implement.object;
            if (tool.getIsPowerTakeoffActive ~= nil and tool:getIsPowerTakeoffActive()) 
            or (tool.isTurnedOn ~= nil and tool.isTurnedOn)
            or (tool.isThreshing ~= nil and tool.isThreshing) 
            or (tool.isInWorkPosition ~= nil and tool.isInWorkPosition) 
            or (tool.foldMoveDirection ~= nil and tool.foldMoveDirection ~= 0) then
                stop = true;
                break;
            end;
        end;
        
        if (self.getIsTurnedOn ~= nil and self:getIsTurnedOn()) -- custom function that returns bool value of your custom "isTurnedOn" variable
        or (self.isTurnedOn ~= nil and self.isTurnedOn)
        or (self.isThreshing ~= nil and self.isThreshing)
        or (self.isInWorkPosition ~= nil and self.isInWorkPosition)
        or (self.foldMoveDirection ~= nil and self.foldMoveDirection ~= 0) then
            stop = true;
        end;
        
        if stop then
            self:onDeactivate(true);
            self:onDeactivateSounds(true);
            stopAI = true;
        end;
    end;
    
    if self.isBroken or (not self.ignitionKey and self.ignitionMode == 2) then
        stopAI = true;
        if self.ignitionMode ~= 0 then
            self:setManualIgnitionMode(0, true);
        end;
    elseif self.fuelFillLevel == 0 then
        stopAI = true;
        if self.ignitionMode ~= 1 then
            self:setManualIgnitionMode(1, true);
        end;
    end;
    
    if stopAI then
        if self:getIsHired() then
            if SpecializationUtil.hasSpecialization(AICombine, self.specializations) then
                AICombine.stopAIThreshing(self, true);
            end;
            if SpecializationUtil.hasSpecialization(AITractor, self.specializations) then
                AITractor.stopAITractor(self, true);
            end;
        end;
    end;
    
    for _, v in ipairs(self.dashLights.table) do
        if v ~= nil and getVisibility(v.node) ~= self.dashLights.activated then
            setVisibility(v.node, self.dashLights.activated);
        end;
    end;
    
    if self.isMotorStarted and not self:getIsHired() and self.isServer and not self.isFuelFilling then
        local fuelUsed = self.fuelUsage * self.idleFuelUsage;

--*******************************************  DURAL ***************************************************
--** real idle fuel usage and do take care of "dt"...            
        if self.isRealistic then
            if self.isActive then
                fuelUsed = 0;
            else
                fuelUsed = RealisticGlobalListener.realDifficultyFX7 * 0.03 * self.realMaxFuelUsage * dt/(1000 * 3600); -- 3% of max fuel usage in Liter per hour
            end;
        end;
        
        if fuelUsed>0 then
            self:setFuelFillLevel(self.fuelFillLevel - fuelUsed);
            g_currentMission.missionStats.fuelUsageTotal = g_currentMission.missionStats.fuelUsageTotal + fuelUsed;
            g_currentMission.missionStats.fuelUsageSession = g_currentMission.missionStats.fuelUsageSession + fuelUsed;
        end;
        
    end;
end;

function BJR_ManualIgnition:onLeave()
    if not self.deactivateOnLeave then
        Utils.setEmittingState(self.exhaustParticleSystems, true)
        self.allowedIgnition = false;
        self.isMotorStarted = true;
        self.ignitionKey = true;

        self.lastAcceleration = 0;
        self.lastRoundPerMinute = 0;
        self.motor.lastMotorRpm = 0;
--*******************************************  DURAL ***************************************************
--** no need to take care of the brake for moreRealistic vehicles
        if self.isServer and not self.isRealistic then
            for k,wheel in pairs(self.wheels) do
                setWheelShapeProps(wheel.node, wheel.wheelShape, 0, self.motor.brakeForce, 0);
            end;
        end;
    else
        self.allowedIgnition = false;
        self.ignitionKey = false;
        self.key.mode = 0;
    end;
end;

function BJR_ManualIgnition:onEnter()
    if not self.ignitionKey then
        self.isMotorStarted = false;
        Motorized.stopSounds(self);
        Utils.setEmittingState(self.exhaustParticleSystems, false)
    else
        if self.ignitionMode == 2 then
            self.allowedIgnition = true;
            self.ignitionKey = true;
            self.key.mode = 1;
        end;    
    end;
end;

function BJR_ManualIgnition:draw()
    if g_currentMission.showHelpText and self.isClient then
        if self.ignitionMode == 0 then
            g_currentMission:addHelpButtonText(string.format(g_i18n:getText("MANUAL_IGNITION_START"), self.typeDesc), InputBinding.MANUAL_IGNITION_KEY);
        elseif self.ignitionMode == 1 then
            g_currentMission:addHelpButtonText(string.format(g_i18n:getText("MANUAL_IGNITION_START"), self.typeDesc), InputBinding.MANUAL_IGNITION_KEY);
        end;
    end;
    
    if self.mpwt > self.time then
        g_currentMission:addWarning(self.mpwtm, 0.018, 0.033);
    end;
end;

function BJR_ManualIgnition:setManualIgnitionMode(ignition, noEventSend)
    BJR_ManualIgnitionEvent.sendEvent(self, ignition, noEventSend);

    self.ignitionMode = ignition;
    self.key.mode = 0;
    self.lastAcceleration = 0;
    
    self.ignitionKey = false;
    self:stopMotor(true);
    self.allowedIgnition = false;
    self.deactivateOnLeave = true;
    self.dashLights.activated = false;
    
    if self.ignitionMode == 1 then
        self.key.mode = 1;
        self.dashLights.activated = true;
    elseif self.ignitionMode == 2 then
        self.ignitionKey = true;
        self.key.mode = 1;
        self.allowedIgnition = true;
    elseif self.ignitionMode > 2 then
        self.ignitionMode = 0;
        self.playedMotorStopSoundNew = false;
    end;
    
--*******************************************  DURAL ***************************************************
--** no need to take care of the brake for moreRealistic vehicles
    if self.isServer and not self.isRealistic and self.ignitionMode ~= 2 then
        for k, wheel in ipairs(self.wheels) do
            setWheelShapeProps(wheel.node, wheel.wheelShape, 0, self.motor.brakeForce, 0);
        end;
    end;
    
end;


BJR_ManualIgnitionEvent = {};
BJR_ManualIgnitionEvent_mt = Class(BJR_ManualIgnitionEvent, Event);

InitEventClass(BJR_ManualIgnitionEvent, "BJR_ManualIgnitionEvent");

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

function BJR_ManualIgnitionEvent:new(vehicle, ignition)
    local self = BJR_ManualIgnitionEvent:emptyNew()
    self.vehicle = vehicle;
    self.ignition = ignition;
    return self;
end;

function BJR_ManualIgnitionEvent:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
    self.ignition = streamReadInt8(streamId);
    self.vehicle = networkGetObject(id);
    self:run(connection);
end;

function BJR_ManualIgnitionEvent:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.vehicle));
    streamWriteInt8(streamId, self.ignition);
end;

function BJR_ManualIgnitionEvent:run(connection)
    self.vehicle:setManualIgnitionMode(self.ignition, true);
    if not connection:getIsServer() then
        g_server:broadcastEvent(BJR_ManualIgnitionEvent:new(self.vehicle, self.ignition), nil, connection, self.object);
    end;
end;
function BJR_ManualIgnitionEvent.sendEvent(vehicle, ignition, noEventSend)
    if noEventSend == nil or noEventSend == false then
        if g_server ~= nil then
            g_server:broadcastEvent(BJR_ManualIgnitionEvent:new(vehicle, ignition), nil, nil, vehicle);
        else
            g_client:getServerConnection():sendEvent(BJR_ManualIgnitionEvent:new(vehicle, ignition));
        end;
    end;
end;