
-- BJR_Windrower
-- Class for all windrowers
-- Note: the animation is not perfectly synchronized, thus do not attach any gameplay relevant stuff to the animation
--
-- @author  Stefan Geiger
-- @date  11/05/08

-- @history		10/08/13 -- Added support for particle systems - JoXXer, BJR-Modding
--
-- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved.

source(Utils.getFilename("$dataS/scripts/vehicles/specializations/SetTurnedOnEvent.lua"));
source(Utils.getFilename("$dataS/scripts/vehicles/specializations/WindrowAreaEvent.lua"));

BJR_Windrower = {};

function BJR_Windrower.prerequisitesPresent(specializations)
    return true;
end;

function BJR_Windrower:load(xmlFile)

    self.setIsTurnedOn = SpecializationUtil.callSpecializationsFunction("setIsTurnedOn");

    self.groundReferenceThreshold = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.groundReferenceNode#threshold"), 0.2);
    self.groundReferenceNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.groundReferenceNode#index"));
    if self.groundReferenceNode == nil then
        self.groundReferenceNode = self.components[1].node;
    end;

    self.animation = {};
    self.animation.animCharSet = 0;
    self.animationEnabled = false;

    local rootNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.animation#rootNode"));

    if rootNode ~= nil then
        self.animation.animCharSet = getAnimCharacterSet(rootNode);
        if self.animation.animCharSet ~= 0 then
            self.animation.clip = getAnimClipIndex(self.animation.animCharSet, getXMLString(xmlFile, "vehicle.animation#animationClip"));
            if self.animation.clip >= 0 then
                assignAnimTrackClip(self.animation.animCharSet, 0, self.animation.clip);
                self.animation.speedScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.animation#speedScale"), 1);
                setAnimTrackSpeedScale(self.animation.animCharSet, self.animation.clip, self.animation.speedScale);
                setAnimTrackLoopState(self.animation.animCharSet, 0, true);
            end;
        end;
    end;

    local numWindrowerDropAreas = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.windrowerDropAreas#count"), 0);
    if numWindrowerDropAreas == 0 then
        print("Warning: No drop areas specified in '"..self.configFileName.."'");
    else
        if numWindrowerDropAreas ~= 1 and numWindrowerDropAreas ~= table.getn(self.cuttingAreas) then
            print("Warning: Number of cutting areas and drop areas should be equal in '"..self.configFileName.."'");
        end;
    end;
    self.windrowerDropAreas = {}
    for i=1, numWindrowerDropAreas do
        self.windrowerDropAreas[i] = {};
        local areanamei = string.format("vehicle.windrowerDropAreas.windrowerDropArea%d", i);
        self.windrowerDropAreas[i].start = Utils.indexToObject(self.components, getXMLString(xmlFile, areanamei .. "#startIndex"));
        self.windrowerDropAreas[i].width = Utils.indexToObject(self.components, getXMLString(xmlFile, areanamei .. "#widthIndex"));
        self.windrowerDropAreas[i].height = Utils.indexToObject(self.components, getXMLString(xmlFile, areanamei .. "#heightIndex"));
    end;

    local numCuttingAreas = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.cuttingAreas#count"), 0);
    self.accumulatedCuttingAreaValues = {};
    self.accumulatedFruitType = FruitUtil.FRUITTYPE_UNKNOWN;
    for i=1, numCuttingAreas do
        self.accumulatedCuttingAreaValues[i] = 0;
    end;

    if self.isClient then
        local windrowerSound = getXMLString(xmlFile, "vehicle.windrowerSound#file");
        if windrowerSound ~= nil and windrowerSound ~= "" then
            windrowerSound = Utils.getFilename(windrowerSound, self.baseDirectory);
            self.windrowerSound = createSample("windrowerSound");
            self.windrowerSoundEnabled = false;
            loadSample(self.windrowerSound, windrowerSound, false);
            self.windrowerSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.windrowerSound#pitchOffset"), 1);
            self.windrowerSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.windrowerSound#volume"), 1.0);
        end;
    end;

    self.isTurnedOn = false;
    self.wasToFast = false;

    self.windrowerGroundFlag = self:getNextDirtyFlag();
	
	
	-- BJR_Windrower changes
	self.grassParticleSystems = {};
	local i=0;
	while true do
		local baseName = string.format("vehicle.grassParticleSystems.grassParticleSystem(%d)", i);
	
		local particleSystem = {};
		particleSystem.ps = {};
		local ps = Utils.loadParticleSystem(xmlFile, particleSystem.ps, baseName, self.components, false, nil, self.baseDirectory)
		if ps == nil then
			break;
		end;
		particleSystem.disableTime = 0;
		particleSystem.isEnabled = false;
		table.insert(self.grassParticleSystems, particleSystem);
		i = i+1;
	end;
	
	self.wheatParticleSystems = {};
	local i=0;
	while true do
		local baseName = string.format("vehicle.wheatParticleSystems.wheatParticleSystem(%d)", i);
	
		local particleSystem = {};
		particleSystem.ps = {};
		local ps = Utils.loadParticleSystem(xmlFile, particleSystem.ps, baseName, self.components, false, nil, self.baseDirectory)
		if ps == nil then
			break;
		end;
		particleSystem.disableTime = 0;
		particleSystem.isEnabled = false;
		table.insert(self.wheatParticleSystems, particleSystem);
		i = i+1;
	end;
	
	
    self.particleSystemFlag = self:getNextDirtyFlag();
end;

function BJR_Windrower:delete()

    if self.windrowerSound ~= nil then
        delete(self.windrowerSound);
    end;

	for k,v in pairs(self.grassParticleSystems) do
		Utils.deleteParticleSystem(v.ps);
	end;
	for k,v in pairs(self.wheatParticleSystems) do
		Utils.deleteParticleSystem(v.ps);
	end;
end;

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

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

function BJR_Windrower:readStream(streamId, connection)
    local isTurnedOn = streamReadBool(streamId);
    self:setIsTurnedOn(isTurnedOn, true);
end;

function BJR_Windrower:writeStream(streamId, connection)
    streamWriteBool(streamId, self.isTurnedOn);
end;

function BJR_Windrower:readUpdateStream(streamId, timestamp, connection)
    if connection:getIsServer() then
        local hasUpdate = streamReadBool(streamId);
        if hasUpdate then
            for k,v in ipairs(self.grassParticleSystems) do
                local enabled = streamReadBool(streamId);
                Utils.setEmittingState(v.ps, enabled);
            end;
            for k,v in ipairs(self.wheatParticleSystems) do
                local enabled = streamReadBool(streamId);
                Utils.setEmittingState(v.ps, enabled);
            end;
        end;
    end;
end;

function BJR_Windrower:writeUpdateStream(streamId, connection, dirtyMask)
    if not connection:getIsServer() then
        if bitAND(dirtyMask, self.ELHOParticleSystemFlag) ~= 0 then
            streamWriteBool(streamId, true);
            for k,v in ipairs(self.grassParticleSystems) do
                streamWriteBool(streamId, v.isEnabled);
            end;
            for k,v in ipairs(self.wheatParticleSystems) do
                streamWriteBool(streamId, v.isEnabled);
            end;
        else
            streamWriteBool(streamId, false);
        end;
    end;
end;

function BJR_Windrower:update(dt)

    if self:getIsActiveForInput() then
        if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA) then
            self:setIsTurnedOn(not self.isTurnedOn);
        end;
    end;
end;

function BJR_Windrower:updateTick(dt)
    self.wasToFast = false;
    if self:getIsActive() then
        if self.isTurnedOn then
            if self.isServer then
                local toFast = self:doCheckSpeedLimit() and self.lastSpeed*3600 > 31;
                if not toFast then
                    local x,y,z = getWorldTranslation(self.groundReferenceNode);
                    local terrainHeight = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, 0, z);
                    if terrainHeight+self.groundReferenceThreshold >= y then
                        local numDropAreas = table.getn(self.windrowerDropAreas);
                        local numAreas = table.getn(self.cuttingAreas);
                        if numDropAreas > 0 and numAreas > 0 then
                            local cuttingAreasSend = {};
                            local dropAreasSend = {};
                            for i=1, numAreas do
                                local cuttingArea = self.cuttingAreas[i];
                                if self:getIsAreaActive(cuttingArea) then
								
                                    local x,_,z = getWorldTranslation(cuttingArea.start);
                                    local x1,_,z1 = getWorldTranslation(cuttingArea.width);
                                    local x2,_,z2 = getWorldTranslation(cuttingArea.height);

                                    table.insert(cuttingAreasSend, {x,z,x1,z1,x2,z2});
								end;
                            end;
                            for i=1, numDropAreas do
                                local dropArea = self.windrowerDropAreas[i];
                                local dx,dy,dz = getWorldTranslation(dropArea.start);
                                local dx1,dy1,dz1 = getWorldTranslation(dropArea.width);
                                local dx2,dy2,dz2 = getWorldTranslation(dropArea.height);
                                table.insert(dropAreasSend, {dx, dz, dx1, dz1, dx2, dz2});
                            end;
                            if table.getn(cuttingAreasSend) > 0 then
                                local cuttingAreasSend, dropAreasSend, fruitType, bitType = WindrowAreaEvent.runLocally(cuttingAreasSend, dropAreasSend, self.accumulatedCuttingAreaValues, self.accumulatedFruitType);
                                if table.getn(cuttingAreasSend) > 0 or table.getn(dropAreasSend) > 0 then
                                    self.accumulatedFruitType = fruitType
									
									-- BJR_Windrower changes 
									if fruitType == FruitUtil.FRUITTYPE_GRASS then
										for k,v in pairs(self.grassParticleSystems) do
											if v.ps ~= nil then
												v.disableTime = self.time + 300;
												if not v.isEnabled then
													v.isEnabled = true;
													self:raiseDirtyFlags(self.particleSystemFlag);
													if self.isClient then
														Utils.setEmittingState(v.ps, true);
													end;
												end;
											end;
										end;
									elseif fruitType == FruitUtil.FRUITTYPE_WHEAT or fruitType == FruitUtil.FRUITTYPE_BARLEY then
										for k,v in pairs(self.wheatParticleSystems) do
											if v.ps ~= nil then
												v.disableTime = self.time + 300;
												if not v.isEnabled then
													v.isEnabled = true;
													self:raiseDirtyFlags(self.particleSystemFlag);
													if self.isClient then
														Utils.setEmittingState(v.ps, true);
													end;
												end;
											end;
										end;
									end;
									-- BJR_Windrower changes end
									
                                    g_server:broadcastEvent(WindrowAreaEvent:new(cuttingAreasSend, dropAreasSend, fruitType, bitType));
                                end;
                            end;
                        end;
                    end;
                end;

                self.wasToFast = toFast;
            end;

            if self.isClient then
                if not self.windrowerSoundEnabled and self:getIsActiveForSound() then
                    playSample(self.windrowerSound, 0, self.windrowerSoundVolume, 0);
                    setSamplePitch(self.windrowerSound, self.windrowerSoundPitchOffset);
                    self.windrowerSoundEnabled = true;
                end;
            end;
        end;
		
		-- BJR_Windrower changes 
		if self.isServer then
			if self.accumulatedFruitType == FruitUtil.FRUITTYPE_GRASS then
				for k,v in pairs(self.grassParticleSystems) do
					if self.time > v.disableTime then
						if v.isEnabled then
							v.isEnabled = false;
							self:raiseDirtyFlags(self.particleSystemFlag);
							if self.isClient then
								Utils.setEmittingState(v.ps, false);
							end;
						end;
					end;
				end;
			elseif self.accumulatedFruitType == FruitUtil.FRUITTYPE_WHEAT or self.accumulatedFruitType == FruitUtil.FRUITTYPE_BARLEY then
				for k,v in pairs(self.wheatParticleSystems) do
					if self.time > v.disableTime then
						if v.isEnabled then
							v.isEnabled = false;
							self:raiseDirtyFlags(self.particleSystemFlag);
							if self.isClient then
								Utils.setEmittingState(v.ps, false);
							end;
						end;
					end;
				end;
			end;
		end;
		-- BJR_Windrower changes end
    end;
end;

function BJR_Windrower:draw()
    if self.isClient then
        if self:getIsActiveForInput(true) then
            if self.isTurnedOn then
                g_currentMission:addHelpButtonText(string.format(g_i18n:getText("turn_off_OBJECT"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA);
            else
                g_currentMission:addHelpButtonText(string.format(g_i18n:getText("turn_on_OBJECT"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA);
            end;
        end

        if self.wasToFast then
            g_currentMission:addWarning(g_i18n:getText("Dont_drive_to_fast") .. "\n" .. string.format(g_i18n:getText("Cruise_control_levelN"), "2"), 0.07+0.022, 0.019+0.029);
        end;
    end;
end;

function BJR_Windrower:onDetach()
    if self.deactivateOnDetach then
        BJR_Windrower.onDeactivate(self);
    else
        BJR_Windrower.onDeactivateSounds(self)
    end;
end;

function BJR_Windrower:onLeave()
    if self.deactivateOnLeave then
        BJR_Windrower.onDeactivate(self);
    else
        BJR_Windrower.onDeactivateSounds(self)
    end;
end;

function BJR_Windrower:onDeactivate()
    if self.animationEnabled then
        disableAnimTrack(self.animation.animCharSet, 0);
        self.animationEnabled = false;
    end;
	
	-- BJR_Windrower changes 
	if self.isClient then
		for k,v in pairs(self.grassParticleSystems) do
			v.isEnabled = false;
			Utils.setEmittingState(v.ps, false);
		end;
	end;
	if self.isClient then
		for k,v in pairs(self.wheatParticleSystems) do
			v.isEnabled = false;
			Utils.setEmittingState(v.ps, false);
		end;
	end;
	-- BJR_Windrower changes end
	
    BJR_Windrower.onDeactivateSounds(self)
    self.isTurnedOn = false;
end;

function BJR_Windrower:onDeactivateSounds()
    if self.windrowerSoundEnabled then
        stopSample(self.windrowerSound);
        self.windrowerSoundEnabled = false;
    end;
end;

function BJR_Windrower:setIsTurnedOn(isTurnedOn, noEventSend)
    SetTurnedOnEvent.sendEvent(self, isTurnedOn, noEventSend)
    self.isTurnedOn = isTurnedOn;

    if not isTurnedOn then
        for k,_ in pairs(self.accumulatedCuttingAreaValues) do
            self.accumulatedCuttingAreaValues[k] = 0;
        end
        if self.windrowerSoundEnabled then
            stopSample(self.windrowerSound);
            self.windrowerSoundEnabled = false;
        end;
        if self.animationEnabled then
            disableAnimTrack(self.animation.animCharSet, 0);
            self.animationEnabled = false;
        end;
    else
        if not self.animationEnabled then
            enableAnimTrack(self.animation.animCharSet, 0);
            self.animationEnabled = true;
        end;
    end;
end;