--
-- KuhnGMD4010
-- Specialization for KuhnGMD4010
--
-- @author  Manuel Leithner
-- @date  26/07/09
--

KuhnGMD4010 = {};

function KuhnGMD4010.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(Attachable, specializations);
end;

function KuhnGMD4010:load(xmlFile)

	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].fenderFixPoint = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#fixpoint"));
		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;
			self.drumNode1 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.drum#index"));
	self.drumNode2 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.drum#index2"));
	self.drumNode3 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.drum#index3"));
	self.drumNode4 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.drum#index4"));
	self.drumNode5 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.drum#index5"));
	self.drumNode6 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.drum#index6"));
	self.drumNode7 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.drum#index7"));
	self.drumNode8 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.drum#index8"));
	
  self.drumRotationScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.drum#rotationScale"), 1);
		    local numRotParts = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.RotParts#count"), 0);
	
	self.arm = {};
	self.arm.node = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.arm#index"));
	local y = Utils.degToRad(Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.arm#minRot"), 0));
	self.arm.minRot = {0,y,0};
	y = Utils.degToRad(Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.arm#maxRot"), 0));
	self.arm.maxRot = {0,y,0};
	self.arm.rotTime = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.arm#rotTime"), 3) * 1000;
	self.arm.liftTime = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.arm#liftTime"), 3) * 1000;
	self.arm.currentRotLimit = {0};
	
	self.supportArm = {};
	self.supportArm.node = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.supportArm#index"));
	self.supportArm.node2 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.supportArm#index2"));
	x = Utils.degToRad(Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.supportArm#minRot"), 0));
	self.supportArm.minRot = {x,0,0};
	x = Utils.degToRad(Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.supportArm#maxRot"), 0));
	self.supportArm.maxRot = {x,0,0};
	x = Utils.degToRad(Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.supportArm#minRot2"), 0));
	self.supportArm.minRot2 = {x,0,0};
	x = Utils.degToRad(Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.supportArm#maxRot2"), 0));
	self.supportArm.maxRot2 = {x,0,0};
	
	
	self.arm.isDown = false;
	self.arm.isExpanded = false;
	
	
	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;

    local mowerSound = getXMLString(xmlFile, "vehicle.mowerSound#file");
    if mowerSound ~= nil and mowerSound ~= "" then
        mowerSound = Utils.getFilename(mowerSound, self.baseDirectory); 
        self.mowerSound = createSample("mowerSound");
        self.mowerSoundEnabled = false;
        loadSample(self.mowerSound, mowerSound, false);
        self.mowerSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.mowerSound#pitchOffset"), 1);
        self.mowerSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.mowerSound#volume"), 1);
    end;

    local numCuttingAreas = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.cuttingAreas#count"), 0);
    for i=1, numCuttingAreas do
        local areanamei = string.format("vehicle.cuttingAreas.cuttingArea%d", i);
        self.cuttingAreas[i].foldMinLimit = Utils.getNoNil(getXMLFloat(xmlFile, areanamei .. "#foldMinLimit"), 0);
        self.cuttingAreas[i].foldMaxLimit = Utils.getNoNil(getXMLFloat(xmlFile, areanamei .. "#foldMaxLimit"), 1);
		self.cuttingAreas[i].grassParticleSystemIndex = getXMLInt(xmlFile, areanamei .. "#particleSystemIndex");
    end;

    self.isTurnedOn = false;
    self.wasToFast = false;	
		
	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;
        table.insert(self.grassParticleSystems, particleSystem);
        i = i+1;
    end;
	
	self.runOnlyOnce = true;
	self.attacherVehicleJoint = nil;
	self.mowerIsAttached = false;
	
	self.isExpanded = false;
	self.isLowered = false;
	
end;

function KuhnGMD4010:delete()
    if self.mowerSound ~= nil then
        delete(self.mowerSound);
    end;
end;

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

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

function KuhnGMD4010:update(dt)
		
	if self.runOnlyOnce then
		setJointRotationLimit(self.componentJoints[2].jointIndex, 2, true, Utils.degToRad(0), Utils.degToRad(0));
		self.runOnlyOnce = false;		
	end;
	
	if self.mowerIsAttached then
		for i=1, table.getn(self.attacherVehicle.attachedImplements) do
			if self.attacherVehicle.attachedImplements[i].object == self then			
				local index = self.attacherVehicle.attachedImplements[i].jointDescIndex;
				self.attacherVehicleJoint = self.attacherVehicle.attacherJoints[index];	
				break;				
			end;
		end;
		self.mowerIsAttached = false;
	end;
	
	
	if self:getIsActive() then
		self.wasToFast = false;
		self.isExpanded = false;
		self.isLowered = false;
		
		local x, y, z = getRotation(self.arm.node);
		if y > Utils.degToRad(85) then
			self.isExpanded = true;
		end;
		
		if self.arm.currentRotLimit[1] > 1 then
			self.isLowered = true;
		end;		
	end;
	
	
		
    if self:getIsActiveForInput() then
		if self.isExpanded then 
	        if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA) then
	            self.isTurnedOn = not self.isTurnedOn;
	        end;
			
			if InputBinding.hasEvent(InputBinding.LOWER_IMPLEMENT) then
				self.arm.isDown = not self.arm.isDown;
			end;
		end;
		if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA2) and not self.isLowered and not self.isTurnedOn then
			self.arm.isExpanded = not self.arm.isExpanded;
		end;	
    end;
	
    if self:getIsActive() then
	
		if self.attacherVehicleJoint ~= nil and self.isExpanded then
			self.attacherVehicleJoint.moveDown = false;
		end;
	
	
		for k,v in pairs(self.grassParticleSystems) do
            if self.time > v.disableTime then
                Utils.setEmittingState(v.ps, false);
            end;
        end;
	
        if self.isTurnedOn then
         if self.drumNode1 ~= nil then
				rotate(self.drumNode1, self.drumRotationScale * 5 * 1, 0, 0);
			end;	
		if self.drumNode2 ~= nil then
				rotate(self.drumNode2, self.drumRotationScale * 5 * 1, 0, 0);
			end;	
		if self.drumNode3 ~= nil then
				rotate(self.drumNode3, self.drumRotationScale * 35 * 0, 15, 0);
			end;
	if self.drumNode4 ~= nil then
				rotate(self.drumNode4, self.drumRotationScale * 35 * 0, 15, 0);
			end;	
	if self.drumNode5 ~= nil then
				rotate(self.drumNode5, self.drumRotationScale * 35 * 0, 15, 0);
			end;	
	if self.drumNode6 ~= nil then
				rotate(self.drumNode6, self.drumRotationScale * 35 * 0, 15, 0);
			end;
	if self.drumNode7 ~= nil then
				rotate(self.drumNode7, self.drumRotationScale * 35 * 0, 15, 0);
			end;
	if self.drumNode8 ~= nil then
				rotate(self.drumNode8, self.drumRotationScale * 35 * 0, 15, 0);
			end;
            local toFast = self:doCheckSpeedLimit() and self.lastSpeed*3600 > 31;
            if not toFast and self.arm.currentRotLimit[1] > 15 then
                local x,y,z = getWorldTranslation(self.groundReferenceNode);
				local foldAnimTime = self.foldAnimTime;
			
				local area = 0;
				local areaWheat = 0;
				local areaBarley = 0;
			
				for k, cuttingArea in pairs(self.cuttingAreas) do
				
					local x,y,z = getWorldTranslation(cuttingArea.start);
					local x1,y1,z1 = getWorldTranslation(cuttingArea.width);
					local x2,y2,z2 = getWorldTranslation(cuttingArea.height);
					
					if k == 1 then
						area = Utils.updateMeadowArea(x, z, x1, z1, x2, z2);
						areaWheat = Utils.cutFruitArea(FruitUtil.FRUITTYPE_WHEAT, x, z, x1, z1, x2, z2);
						areaBarley = Utils.cutFruitArea(FruitUtil.FRUITTYPE_BARLEY, x, z, x1, z1, x2, z2);
						
						if self.attacherVehicle.movingDirection ~= -1 then
							area = area + Utils.updateFruitCutLongArea(FruitUtil.FRUITTYPE_GRASS, x, z, x1, z1, x2, z2, 0);		
						else
							if areaWheat > 0 then	
								local old, total = Utils.getFruitWindrowArea(FruitUtil.FRUITTYPE_WHEAT, x, z, x1, z1, x2, z2);
								local value = 1+math.floor(old / total + 0.7);
								value = math.min(value, g_currentMission.maxWindrowValue);
								Utils.updateFruitWindrowArea(FruitUtil.FRUITTYPE_WHEAT, x, z, x1, z1, x2, z2, value, true);	
							end;
							
							if areaBarley > 0 then
								local old, total = Utils.getFruitWindrowArea(FruitUtil.FRUITTYPE_BARLEY, x, z, x1, z1, x2, z2);
								local value = 1+math.floor(old / total + 0.7);
								value = math.min(value, g_currentMission.maxWindrowValue);
								Utils.updateFruitWindrowArea(FruitUtil.FRUITTYPE_BARLEY, x, z, x1, z1, x2, z2, value, true);							
							end;
						end;
						
						if g_currentMission.environment.lastRainScale <= 0.1 and g_currentMission.environment.timeSinceLastRain > 30 then
							if area > 0 or areaWheat > 0 or areaBarley > 0 then
								if cuttingArea.grassParticleSystemIndex ~= nil then
									ps = self.grassParticleSystems[cuttingArea.grassParticleSystemIndex+1];
									if ps ~= nil then
										ps.disableTime = self.time + 20;
										Utils.setEmittingState(ps.ps, true);
									end;
								end;					
							end;
						end;
						
					else
						if self.attacherVehicle.movingDirection ~= -1 then
							if area > 0 then
								local old, total = Utils.getFruitCutLongArea(FruitUtil.FRUITTYPE_DRYGRASS, x, z, x1, z1, x2, z2);							
								local value = 1+math.floor(old / total + 0.7);
								value = math.min(value, g_currentMission.maxWindrowValue);
								Utils.updateFruitCutLongArea(FruitUtil.FRUITTYPE_GRASS, x, z, x1, z1, x2, z2, value, true);						
							end;
							
							if areaWheat > 0 then							
								local old, total = Utils.getFruitWindrowArea(FruitUtil.FRUITTYPE_WHEAT, x, z, x1, z1, x2, z2);
								local value = 1+math.floor(old / total + 0.7);
								value = math.min(value, g_currentMission.maxWindrowValue);
								Utils.updateFruitWindrowArea(FruitUtil.FRUITTYPE_WHEAT, x, z, x1, z1, x2, z2, value, true);	
							end;
							
							if areaBarley > 0 then
								local old, total = Utils.getFruitWindrowArea(FruitUtil.FRUITTYPE_BARLEY, x, z, x1, z1, x2, z2);
								local value = 1+math.floor(old / total + 0.7);
								value = math.min(value, g_currentMission.maxWindrowValue);
								Utils.updateFruitWindrowArea(FruitUtil.FRUITTYPE_BARLEY, x, z, x1, z1, x2, z2, value, true);							
							end;
						end;							
					end;
				end;
            end;

            if not self.mowerSoundEnabled and self:getIsActiveForSound() then
                setSamplePitch(self.mowerSound, self.mowerSoundPitchOffset);
                playSample(self.mowerSound, 0, self.mowerSoundVolume, 0);
                self.mowerSoundEnabled = true;
            end;

            self.wasToFast = toFast;

        else
            if self.mowerSoundEnabled then
                stopSample(self.mowerSound);
                self.mowerSoundEnabled = false;
            end;
        end;
		
		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].fenderFixPoint);
			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, 1, 0);
			if self.hydraulics[i].punch ~= nil then
				local distance = Utils.vector3Length(ax-bx, ay-by, az-bz);
				setTranslation(self.hydraulics[i].punch, 0, 0, distance-self.hydraulics[i].punchDistance);
			end;	
		end;		
		
		local x, y, z = getRotation(self.arm.node);	
		local rot = {x,y,z};
		self.arm.maxRot[1] = x;
		self.arm.minRot[1] = x;
		local newRot = Utils.getMovedLimitedValues(rot, self.arm.maxRot, self.arm.minRot, 3, self.arm.rotTime, dt, not self.arm.isExpanded);
		setRotation(self.arm.node, unpack(newRot));	
		
		--if math.abs(newRot[2] - y) > 0.001 then
		
			setJointFrame(self.componentJoints[1].jointIndex, 0, self.componentJoints[1].jointNode);
			
			if not self.isExpanded then
				setJointFrame(self.componentJoints[2].jointIndex, 0, self.componentJoints[2].jointNode);
				setJointRotationLimit(self.componentJoints[2].jointIndex, 2, true, Utils.degToRad(0), Utils.degToRad(0));
			else
				setJointRotationLimit(self.componentJoints[2].jointIndex, 2, true, Utils.degToRad(-19), Utils.degToRad(19));
			end;
		--end;
		
		
		x, y, z = getRotation(self.arm.node);
		rot = {x,y,z};			
		
		local newRotLimit = {0,0,0};
		newRotLimit = Utils.getMovedLimitedValues(self.arm.currentRotLimit, {30}, {0}, 1, self.arm.liftTime * 2, dt, not self.arm.isDown);
		if math.abs(newRotLimit[1] - self.arm.currentRotLimit[1]) > 0.001 then
			setJointRotationLimit(self.componentJoints[1].jointIndex, 0, true, Utils.degToRad(-newRotLimit[1]), Utils.degToRad(newRotLimit[1]));
		end;	
		
		self.arm.currentRotLimit = newRotLimit;	
    end;
end;

function KuhnGMD4010:draw()
	if self.isActive then
		if self.isExpanded 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;
			
			if self.wasToFast then
		        g_currentMission:addWarning(g_i18n:getText("Dont_drive_to_fast") .. "\n" .. string.format(g_i18n:getText("Cruise_control_levelN"), "2", InputBinding.getButtonKeyName(InputBinding.SPEED_LEVEL2)), 0.07+0.022, 0.019+0.029);
		    end;
		end;
		
		if not self.isLowered and not self.isTurnedOn then
			if self.arm.isExpanded then
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("arm_fold"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA2);
			else
				g_currentMission:addHelpButtonText(string.format(g_i18n:getText("arm_expand"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA2);
			end;
		end;
	end;
end;


function KuhnGMD4010:onAttach(attacherVehicle)

	setRotation(self.supportArm.node, unpack(self.supportArm.maxRot));
	setRotation(self.supportArm.node2, unpack(self.supportArm.maxRot2));
	self.mowerIsAttached = true;

end;

function KuhnGMD4010:onDetach()
    if self.deactivateOnDetach then
        KuhnGMD4010.onDeactivate(self);
    else
        KuhnGMD4010.onDeactivateSounds(self)
    end;
	setRotation(self.supportArm.node, unpack(self.supportArm.minRot));
	setRotation(self.supportArm.node2, unpack(self.supportArm.minRot2));
	self.attacherVehicleJoint = nil;
end;


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


function KuhnGMD4010:onDeactivate()
    KuhnGMD4010.onDeactivateSounds(self)
    for k,v in pairs(self.grassParticleSystems) do
        Utils.setEmittingState(v.ps, false);
    end;
    self.isTurnedOn = false;
end;

function KuhnGMD4010:onDeactivateSounds()
    if self.mowerSoundEnabled then
        stopSample(self.mowerSound);
        self.mowerSoundEnabled = false;
    end;
end;




