--
-- workMode for Claas Jaguar 980
-- 
-- v 0.3
-- date 30.10.2013

-- webalizer 


workMode = {};
local workMode_directory = g_currentModDirectory;

function workMode:prerequisitesPresent(specializations)
	--return SpecializationUtil.hasSpecialization(combine, specializations);
	return true;
end;

function workMode:load(xmlFile)

	self.setIsCutterActive = SpecializationUtil.callSpecializationsFunction("setIsCutterActive");
	self.setIsCylinderActive = SpecializationUtil.callSpecializationsFunction("setIsCylinderActive");
	self.startCylinder = SpecializationUtil.callSpecializationsFunction("startCylinder");
	self.stopCylinder = SpecializationUtil.callSpecializationsFunction("stopCylinder");
	self.startCutter = SpecializationUtil.callSpecializationsFunction("startCutter");
	self.stopCutter = SpecializationUtil.callSpecializationsFunction("stopCutter");

	if self.isClient then
        local drumStartSound = getXMLString(xmlFile, "vehicle.drumStartSound#file");
        if drumStartSound ~= nil and drumStartSound ~= "" then
            drumStartSound = Utils.getFilename(drumStartSound, self.baseDirectory);
            self.drumStartSound = createSample("drumStartSound");
            loadSample(self.drumStartSound, drumStartSound, false);
            self.drumStartSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.drumStartSound#pitchOffset"), 1);
            self.drumStartSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.drumStartSound#volume"), 1.0);
            setSamplePitch(self.drumStartSound, self.drumStartSoundPitchOffset);
        end;
		local drumStopSound = getXMLString(xmlFile, "vehicle.drumStopSound#file");
        if drumStopSound ~= nil and drumStopSound ~= "" then
            drumStopSound = Utils.getFilename(drumStopSound, self.baseDirectory);
            self.drumStopSound = createSample("drumStopSound");
            loadSample(self.drumStopSound, drumStopSound, false);
            self.drumStopSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.drumStopSound#pitchOffset"), 1);
            self.drumStopSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.drumStopSound#volume"), 1.0);
            setSamplePitch(self.drumStopSound, self.drumStopSoundPitchOffset);
        end;	
        self.drumIdleSoundActive = false;
        local drumIdleSound = getXMLString(xmlFile, "vehicle.drumIdleSound#file");
        if drumIdleSound ~= nil and drumIdleSound ~= "" then
            drumIdleSound = Utils.getFilename(drumIdleSound, self.baseDirectory);
            self.drumIdleSound = createSample("drumIdleSound");
            loadSample(self.drumIdleSound, drumIdleSound, false);
            self.drumIdleSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.drumIdleSound#pitchOffset"), 1);
            self.drumIdleSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.drumIdleSound#volume"), 1.0);
            setSamplePitch(self.drumIdleSound, self.drumIdleSoundPitchOffset);

        end;
		
        local cutterStartSound = getXMLString(xmlFile, "vehicle.cutterStartSound#file");
        if cutterStartSound ~= nil and cutterStartSound ~= "" then
            cutterStartSound = Utils.getFilename(cutterStartSound, self.baseDirectory);
            self.cutterStartSound = createSample("cutterStartSound");
            loadSample(self.cutterStartSound, cutterStartSound, false);
            self.cutterStartSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.cutterStartSound#pitchOffset"), 1);
            self.cutterStartSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.cutterStartSound#volume"), 1.0);
            setSamplePitch(self.cutterStartSound, self.cutterStartSoundPitchOffset);
        end;
		local cutterStopSound = getXMLString(xmlFile, "vehicle.cutterStopSound#file");
        if cutterStopSound ~= nil and cutterStopSound ~= "" then
            cutterStopSound = Utils.getFilename(cutterStopSound, self.baseDirectory);
            self.cutterStopSound = createSample("cutterStopSound");
            loadSample(self.cutterStopSound, cutterStopSound, false);
            self.cutterStopSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.cutterStopSound#pitchOffset"), 1);
            self.cutterStopSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.cutterStopSound#volume"), 1.0);
            setSamplePitch(self.cutterStopSound, self.cutterStopSoundPitchOffset);
        end;
        self.cutterIdleSoundActive = false;
        local cutterIdleSound = getXMLString(xmlFile, "vehicle.cutterIdleSound#file");
        if cutterIdleSound ~= nil and cutterIdleSound ~= "" then
            cutterIdleSound = Utils.getFilename(cutterIdleSound, self.baseDirectory);
            self.cutterIdleSound = createSample("cutterIdleSound");
            loadSample(self.cutterIdleSound, cutterIdleSound, false);
            self.cutterIdleSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.cutterIdleSound#pitchOffset"), 1);
            self.cutterIdleSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.cutterIdleSound#volume"), 1.0);
            setSamplePitch(self.cutterIdleSound, self.cutterIdleSoundPitchOffset);

        end;
	end;

	self.startThreshing = Utils.overwrittenFunction(self.startThreshing, workMode.startThreshing);
	self.stopThreshing = Utils.overwrittenFunction(self.stopThreshing, workMode.stopThreshing);

	self.origFuelUsage = self.fuelUsage;
	self.origMinRpm = self.motor.minRpm;
	self.origMaxRpm = self.motor:getMaxRpm();

	self.cuttingAmount = 0;
	self.area = 0;
	self.soundTime = 0;
	self.cylinderStartTime = getSampleDuration(self.drumStartSound);
	self.cylinderWaitTime = 0;
	self.cutterStartTime = getSampleDuration(self.cutterStartSound);
	self.cutterWaitTime = 0;
	self.threshingSoundPitch = 0;
	self.isCutterActive = false;
	self.isCylinderActive = false;
	self.cylinderSetManual = false;
	self.cutterSetManual = false;

	self.cuttingViolationMaxTime = 50;
	self.cuttingViolationTimer = self.cuttingViolationMaxTime;

	self.rotorFan2 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.rotorFan2#index"));
end;

function workMode:update(dt)

	if self.numAttachedCutters > 0 then
		if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA2) then
			for k,v in pairs(self.attachedCutters) do
				myCutter = v.object;			
				if not myCutter:isLowered() then
					self:setJointMoveDown(self.attachedCutters[k].jointDescIndex, true);
				end;
			end;
		end;
	end;

	if self:getIsActive() and self.isMotorStarted then
		if self.isClient and self:getIsActiveForInput(false) and not self:hasInputConflictWithSelection() then
			if InputBinding.hasEvent(InputBinding.workMode_cutter) then
				if self.time > self.cylinderWaitTime then
					self:setIsCutterActive(not self.isCutterActive, true);
				end;
			end;

			if InputBinding.hasEvent(InputBinding.workMode_ccylinder) then
				if not self.isThreshing and not self.isCutterActive then
					self:setIsCylinderActive(not self.isCylinderActive, true);
				end;
			end;
		end;

		if self.isClient then
			if self.isCylinderActive then
				if self:getIsActiveForSound() then
					if self.drumIdleSound ~= nil then
						if not self.drumIdleSoundActive then
							if self.drumStartSound == nil or not isSamplePlaying(self.drumStartSound) or getSamplePlayOffset(self.drumStartSound) >= getSampleDuration(self.drumStartSound)-1.8*dt then
								playSample(self.drumIdleSound, 0, self.drumIdleSoundVolume, 0);
								self.drumIdleSoundActive = true;
							end;
						end;
					end;
				end;
			end;
			if self.isCutterActive then
				if self:getIsActiveForSound() then
					if self.cutterIdleSound ~= nil then
						if not self.cutterIdleSoundActive then
							if self.cutterStartSound == nil or not isSamplePlaying(self.cutterStartSound) or getSamplePlayOffset(self.cutterStartSound) >= getSampleDuration(self.cutterStartSound)-1.8*dt then
								playSample(self.cutterIdleSound, 0, self.cutterIdleSoundVolume, 0);
								self.cutterIdleSoundActive = true;
							end;
						end;
					end;
				end;
			end;
        end;

		for k,v in pairs(self.attachedCutters) do
				self.myCutter = v.object;
		end;
		
		if self.isCutterActive then

			for k,area in pairs(self.myCutter.cuttingAreas) do
				local x,y,z = getWorldTranslation(area.start);
				local x1,y1,z1 = getWorldTranslation(area.width);
				local x2,y2,z2 = getWorldTranslation(area.height);
				
				for fruitType,_ in pairs(self.myCutter.fruitTypes) do
					local desc = FruitUtil.fruitIndexToDesc[fruitType];
					if desc ~= nil then
						self.area = Utils.getFruitArea(desc.index, x, z, x1, z1, x2, z2);
					end;
				end;

				if self.area > 0 and self.movingDirection > 0 then
					self.soundTime = self.time + 1500;
					self.cuttingAmount = self.area;
				end;

				if self.isThreshing then
					if self.soundTime > self.time then
						if self.cuttingAmount > 10 then
							self.threshingSoundPitch = getSamplePitch(self.threshingSound) - 0.0015;
							if self.threshingSoundPitch < 0.92 then
								self.threshingSoundPitch = 0.92
							end;
							setSamplePitch(self.threshingSound, self.threshingSoundPitch);
						end;
					else
						self.threshingSoundPitch = getSamplePitch(self.threshingSound) + 0.0015;
						if self.threshingSoundPitch > 1 then
							self.threshingSoundPitch = 1;
						end;
						setSamplePitch(self.threshingSound, self.threshingSoundPitch);
					end
				end;
			end;
		end;


		if self.isThreshing then
			self.motor.minRpm = self.motor.minRpm - 20;
			if self.motor.minRpm < -self.origMaxRpm*0.9 then
				self.motor.minRpm = -self.origMaxRpm*0.9;
			end;		
			self.fuelUsage = (self.origFuelUsage*(-self.motor.minRpm/50))*1.1;
		else
			self.motor.minRpm = self.motor.minRpm + 20;
			if self.motor.minRpm > self.origMinRpm then
				self.motor.minRpm = self.origMinRpm;
			end;
			self.fuelUsage = self.origFuelUsage*(-self.motor.minRpm/50);
		end;
		
		if self.isCylinderActive then
			if self.rotorFan ~= nil and not self.isThreshing then
				rotate(self.rotorFan, dt*0.005, 0, 0);
			end;
			if self.rotorFan2 ~= nil then
				rotate(self.rotorFan2, -(dt*0.005), 0, 0);
			end;
		end;	

		if self.soundTime > self.time then
			if not self.isThreshing then
				self.cuttingViolationTimer = self.cuttingViolationTimer - dt;
			else
				self.cuttingViolationTimer = self.cuttingViolationMaxTime;
			end;
		else
			self.cuttingViolationTimer = self.cuttingViolationMaxTime
		end;		
	end;
end;

function workMode:updateTick(dt)


end;



function workMode:draw()
	if self.isMotorStarted then
		if self.isCylinderActive and self.time > self.cylinderWaitTime and self.numAttachedCutters > 0 then
			if self.isCutterActive then
				g_currentMission:addHelpButtonText(self.myCutter.typeDesc.." "..g_i18n:getText("workMode_deactivate"), InputBinding.workMode_cutter);
			else
				g_currentMission:addHelpButtonText(self.myCutter.typeDesc.." "..g_i18n:getText("workMode_activate"), InputBinding.workMode_cutter);
			end;
		end;
		if not self.isThreshing then
			if self.isCylinderActive then
				if not self.isCutterActive then
					g_currentMission:addHelpButtonText(g_i18n:getText("workMode_ccylinder").." "..g_i18n:getText("workMode_deactivate"), InputBinding.workMode_ccylinder);
				end;
			else
				g_currentMission:addHelpButtonText(g_i18n:getText("workMode_ccylinder").." "..g_i18n:getText("workMode_activate"), InputBinding.workMode_ccylinder);
			end;
		end;
		if math.abs(self.cuttingViolationTimer - self.cuttingViolationMaxTime) > 2 then
			g_currentMission:addWarning(string.format(g_i18n:getText("workMode_warning"), InputBinding.getKeyNamesOfDigitalAction(InputBinding.IMPLEMENT_EXTRA)), 0.05, 0.025+0.007);
		end;
	end;
end;

function workMode:startCylinder()
    if not self.isCylinderActive and self.isMotorStarted then
            self.isCylinderActive = true;
			self.cylinderWaitTime = self.cylinderStartTime + self.time;
            if self.isClient then
                if self.drumStartSound ~= nil then
                    if self:getIsActiveForSound() then
                        playSample(self.drumStartSound, 1, self.drumStartSoundVolume, 0);
                    end;
                end;
				for _, v in pairs(self.combineThreshingScrollers) do
					if v.toggleVisibility then
						setVisibility(v.node, true);
					end;
				end;

            end;
    end;
end;

function workMode:stopCylinder()
    if self.isCylinderActive then
        if self.isClient then
            if self.drumIdleSoundActive then
                stopSample(self.drumIdleSound);
                self.drumIdleSoundActive = false;
            end
            if self.drumStartSound ~= nil then
                stopSample(self.drumStartSound);
            end
            if self.drumStopSound ~= nil and self:getIsActiveForSound() then
                playSample(self.drumStopSound, 1, self.drumStopSoundVolume, 0);
            end
        end;
		self.isCylinderActive = false;
    end;
end;

function workMode:startCutter()

	if not self.isCutterActive and self.isCylinderActive then	
		if self.numAttachedCutters > 0 then
	            self.chopperActivated = self.defaultChopperState;
				self.isCutterActive = true;
				self.cutterWaitTime = self.cutterStartTime + self.time;
				for cutter,implement in pairs(self.attachedCutters) do
					cutter:onStartReel();
				end;
				
				if self.threshingStartAnimation ~= nil and self.playAnimation ~= nil then
					self:playAnimation(self.threshingStartAnimation, self.threshingStartAnimationSpeedScale, nil, true);
				end;			
				
				if self.isClient then
					if self.cutterStartSound ~= nil then
						if self:getIsActiveForSound() then
							playSample(self.cutterStartSound, 1, self.cutterStartSoundVolume, 0);
						end;
					end;

					for _, v in pairs(self.combineThreshingScrollers) do
						if v.toggleVisibility then
							setVisibility(v.node, true);
						end
					end
				end;
		end;
	end;

	
end;

function workMode:stopCutter()

    if self.isCutterActive then
        if self.isClient then
            if self.cutterIdleSoundActive then
                stopSample(self.cutterIdleSound);
                self.cutterIdleSoundActive = false;
            end
            if self.cutterStartSound ~= nil then
                stopSample(self.cutterStartSound);
            end
            if self.cutterStopSound ~= nil and self:getIsActiveForSound() then
                playSample(self.cutterStopSound, 1, self.cutterStopSoundVolume, 0);
            end
			for _, v in pairs(self.combineThreshingScrollers) do
                if v.toggleVisibility then
                    setVisibility(v.node, false);
                end
            end
        end;
		self.isCutterActive = false;
		for cutter,implement in pairs(self.attachedCutters) do
            cutter:onStopReel();
        end;
    end;

end;


function workMode:startThreshing()

    if not self.isThreshing then
        if self.numAttachedCutters > 0 then
            self.isThreshing = true;
            if not self.isCylinderActive then
				self:setIsCylinderActive(true, false);
			end;
			if not self.isCutterActive then
				self:setIsCutterActive(true, false);
			end;


			if self.threshingStartSound ~= nil then
				if self:getIsActiveForSound() then
					playSample(self.threshingStartSound, 1, self.threshingStartSoundVolume, 0);
				end;
			end;

        end;
    end;
end;

function workMode:stopThreshing()

    if self.isThreshing then

        if self.isClient then
            if self.threshingSoundActive then
                stopSample(self.threshingSound);
                self.threshingSoundActive = false;
            end
            if self.threshingStartSound ~= nil then
                stopSample(self.threshingStartSound);
            end

            if self.threshingStopSound ~= nil and self:getIsActiveForSound() then
                playSample(self.threshingStopSound, 1, self.threshingStopSoundVolume, 0);
            end
            if self.threshingSound3D ~= nil then
                setVisibility(self.threshingSound3D, false);
            end
			if not self.cutterSetManual then
				self:setIsCutterActive(false);
			end;
			if not self.cylinderSetManual then
				self:setIsCylinderActive(false);
			end;
        end;

        self:setCombineIsFilling(false, false, true);

        self.chopperActivated = self.defaultChopperState;
        self.isThreshing = false;

        if self.threshingStartAnimation ~= nil and self.playAnimation ~= nil then
            self:playAnimation(self.threshingStartAnimation, -self.threshingStartAnimationSpeedScale, nil, true);
        end
    end;

end;

function workMode:setIsCutterActive(isCutterActive, setManual, noEventSend)
    if isCutterActive ~= self.isCutterActive then
        if noEventSend == nil or noEventSend == false then
            if g_server ~= nil then
                g_server:broadcastEvent(WorkModeCutterEvent:new(self, isCutterActive, setManual), nil, nil, self);
            else
                g_client:getServerConnection():sendEvent(WorkModeCutterEvent:new(self, isCutterActive, setManual));
            end;
        end;
        if isCutterActive then
            self:startCutter();
        else
            self:stopCutter();
        end;
		self.cutterSetManual = setManual;
    end;
end;

function workMode:setIsCylinderActive(isCylinderActive, setManual, noEventSend)
    if isCylinderActive ~= self.isCylinderActive then
        if noEventSend == nil or noEventSend == false then
            if g_server ~= nil then
                g_server:broadcastEvent(WorkModeCylinderEvent:new(self, isCylinderActive, setManual), nil, nil, self);
            else
                g_client:getServerConnection():sendEvent(WorkModeCylinderEvent:new(self, isCylinderActive, setManual));
            end;
        end;
		

        if isCylinderActive then
            self:startCylinder();
        else
            self:stopCylinder();
        end;
		self.cylinderSetManual = setManual;
    end;
end;

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

end;

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

end;

function workMode:updateTick(dt)
	
end;

function workMode:readStream(streamId, connection)
    local isCutterActive = streamReadBool(streamId);
    local isCylinderActive = streamReadBool(streamId);
	local cylinderSetManual = streamReadBool(streamId);
	local cutterSetManual = streamReadBool(streamId);

    self:setIsCutterActive(isCutterActive, cutterSetManual, true);
    self:setIsCylinderActive(isCylinderActive, cylinderSetManual, true);
end;

function workMode:writeStream(streamId, connection)  
    streamWriteBool(streamId, self.isCutterActive);
    streamWriteBool(streamId, self.isCylinderActive);
    streamWriteBool(streamId, self.cutterSetManual);
    streamWriteBool(streamId, self.cylinderSetManual);
end;

function workMode:delete()	
    if self.drumStartSound ~= nil then
        delete(self.drumStartSound);
    end;
    if self.drumIdleSound ~= nil then
        delete(self.drumIdleSound);
        self.drumIdleSoundActive = false;
    end;
    if self.drumStopSound ~= nil then
        delete(self.drumStopSound);
    end;
    if self.cutterStartSound ~= nil then
        delete(self.cutterStartSound);
    end;
    if self.cutterIdleSound ~= nil then
        delete(self.cutterIdleSound);
        self.cutterIdleSoundActive = false;
    end;
    if self.cutterStopSound ~= nil then
        delete(self.cutterStopSound);
    end;
end;