--
-- Baler
-- Class for all Balers
--
-- @author  Stefan Geiger
-- @date  10/09/08
--
-- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved.

Sipma = {};

function Sipma.prerequisitesPresent(specializations)
    Vehicle.registerJointType("trailerLow");
	return SpecializationUtil.hasSpecialization(Trailer, specializations);
end;

function Sipma:load(xmlFile)

--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ORGINAL BALER^^^^^^^^^^^^^^^^^^^^^^--


    self.getTimeFromLevel = Sipma.getTimeFromLevel;
    self.moveBales = SpecializationUtil.callSpecializationsFunction("moveBales");
    self.moveBale = SpecializationUtil.callSpecializationsFunction("moveBale");
    self.allowFillType = Sipma.allowFillType;

    self.fillScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.fillScale#value"), 1);

    local firstBaleMarker = getXMLFloat(xmlFile, "vehicle.baleAnimation#firstBaleMarker");
    if firstBaleMarker ~= nil then
        local baleAnimCurve = AnimCurve:new(linearInterpolatorN);
        local keyI = 0;
        while true do
            local key = string.format("vehicle.baleAnimation.key(%d)", keyI);
            local t = getXMLFloat(xmlFile, key.."#time");
            local x,y,z = Utils.getVectorFromString(getXMLString(xmlFile, key.."#pos"));
            if x == nil or y == nil or z == nil then
                break;
            end;
            local rx, ry, rz = Utils.getVectorFromString(getXMLString(xmlFile, key.."#rot"));
            rx = math.rad(Utils.getNoNil(rx, 0));
            ry = math.rad(Utils.getNoNil(ry, 0));
            rz = math.rad(Utils.getNoNil(rz, 0));
            baleAnimCurve:addKeyframe({ v={x, y, z, rx, ry, rz}, time = t});
            keyI = keyI +1;
        end;
        if keyI > 0 then
            self.baleAnimCurve = baleAnimCurve;
            self.baleAnimRoot = Utils.getNoNil(Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.baleAnimation#node")), self.components[1].node);
            self.firstBaleMarker = firstBaleMarker;
            --self.baleFilename = Utils.getNoNil(getXMLString(xmlFile, "vehicle.baleAnimation#filename"), "data/maps/models/objects/strawbale/strawbaleBaler.i3d");

            self.baleTypes = {};
            local i = 0;
            while true do
                local key = string.format("vehicle.baleTypes.baleType(%d)", i);
                local t = getXMLString(xmlFile, key.."#fruitType");
                local filename = getXMLString(xmlFile, key.."#filename");
                if t==nil or filename==nil then
                    break;
                end;

                local entry = {};
                entry.filename = filename;
                local desc = FruitUtil.fruitTypes[t];
                if desc ~= nil then
                    self.baleTypes[desc.index] = entry;

                    if self.defaultBaleType == nil then
                        self.defaultBaleType = entry;
                    end;
                end;
                i = i +1;
            end;
            if self.defaultBaleType == nil then
                self.baleTypes = nil;
            end;
        end;
    end;

    local balerSound = getXMLString(xmlFile, "vehicle.balerSound#file");
    if balerSound ~= nil and balerSound ~= "" then
        balerSound = Utils.getFilename(balerSound, self.baseDirectory);
        self.balerSound = createSample("balerSound");
        self.balerSoundEnabled = false;
        loadSample(self.balerSound, balerSound, false);
        self.balerSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.balerSound#pitchOffset"), 1);
        self.balerSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.balerSound#volume"), 1);
    end;

    self.baleMoveLastTime = 0;

    self.bales = {};
    self.wasToFast = false;
    self.isTurnedOn = false;
--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ORGINAL BALER^^^^^^^^^^^^^^^^^^^^^^--
--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^END^^^^^^^^^^^^^^^^^^^^^^--
	
	
	
 local rotationPartNodezaczep = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.zaczep#index"));
    if rotationPartNodezaczep ~= nil then
        self.rotationPartzaczep = {};
        self.rotationPartzaczep.node = rotationPartNodezaczep;

        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.rotationPartzaczep#minRot"));
        self.rotationPartzaczep.minRot = {};
        self.rotationPartzaczep.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationPartzaczep.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationPartzaczep.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.zaczep#maxRot"));
        self.rotationPartzaczep.maxRot = {};
        self.rotationPartzaczep.maxRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationPartzaczep.maxRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationPartzaczep.maxRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        self.rotationPartzaczep.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.zaczep#rotTime"), 2)*1000;
        self.rotationPartzaczep.touchRotLimit = Utils.degToRad(Utils.getNoNil(getXMLString(xmlFile, "vehicle.zaczep#touchRotLimit"), 10));
    end;	
	 local rotationPartNodeklapa = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.klapa#index"));
    if rotationPartNodeklapa ~= nil then
        self.rotationPartklapa = {};
        self.rotationPartklapa.node = rotationPartNodeklapa;

        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.rotationPartklapa#minRot"));
        self.rotationPartklapa.minRot = {};
        self.rotationPartklapa.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationPartklapa.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationPartklapa.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.klapa#maxRot"));
        self.rotationPartklapa.maxRot = {};
        self.rotationPartklapa.maxRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationPartklapa.maxRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationPartklapa.maxRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        self.rotationPartklapa.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.klapa#rotTime"), 2)*1000;
        self.rotationPartklapa.touchRotLimit = Utils.degToRad(Utils.getNoNil(getXMLString(xmlFile, "vehicle.klapa#touchRotLimit"), 10));
    end;
 local rotationPartNodepodbierak = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.podbierak#index"));
    if rotationPartNodepodbierak ~= nil then
        self.rotationPartpodbierak = {};
        self.rotationPartpodbierak.node = rotationPartNodepodbierak;

        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.rotationPartpodbierak#minRot"));
        self.rotationPartpodbierak.minRot = {};
        self.rotationPartpodbierak.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationPartpodbierak.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationPartpodbierak.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.podbierak#maxRot"));
        self.rotationPartpodbierak.maxRot = {};
        self.rotationPartpodbierak.maxRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationPartpodbierak.maxRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationPartpodbierak.maxRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        self.rotationPartpodbierak.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.podbierak#rotTime"), 2)*1000;
        self.rotationPartpodbierak.touchRotLimit = Utils.degToRad(Utils.getNoNil(getXMLString(xmlFile, "vehicle.podbierak#touchRotLimit"), 10));
    end;
	
local rotationPartNodemlot = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.mlot#index"));
    if rotationPartNodemlot ~= nil then
        self.rotationPartmlot = {};
        self.rotationPartmlot.node = rotationPartNodemlot;

        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.rotationPartmlot#minRot"));
        self.rotationPartmlot.minRot = {};
        self.rotationPartmlot.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationPartmlot.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationPartmlot.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.mlot#maxRot"));
        self.rotationPartmlot.maxRot = {};
        self.rotationPartmlot.maxRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationPartmlot.maxRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationPartmlot.maxRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        self.rotationPartmlot.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.mlot#rotTime"), 2)*1000;
        self.rotationPartmlot.touchRotLimit = Utils.degToRad(Utils.getNoNil(getXMLString(xmlFile, "vehicle.mlot#touchRotLimit"), 10));
    end
 
 local rotationPartNodemlot2 = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.mlot2#index"));
    if rotationPartNodemlot2 ~= nil then
        self.rotationPartmlot2 = {};
        self.rotationPartmlot2.node = rotationPartNodemlot2;

        local x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.rotationPartmlot2#minRot"));
        self.rotationPartmlot2.minRot = {};
        self.rotationPartmlot2.minRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationPartmlot2.minRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationPartmlot2.minRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        x, y, z = Utils.getVectorFromString(getXMLString(xmlFile, "vehicle.mlot2#maxRot"));
        self.rotationPartmlot2.maxRot = {};
        self.rotationPartmlot2.maxRot[1] = Utils.degToRad(Utils.getNoNil(x, 0));
        self.rotationPartmlot2.maxRot[2] = Utils.degToRad(Utils.getNoNil(y, 0));
        self.rotationPartmlot2.maxRot[3] = Utils.degToRad(Utils.getNoNil(z, 0));

        self.rotationPartmlot2.rotTime = Utils.getNoNil(getXMLString(xmlFile, "vehicle.mlot2#rotTime"), 2)*1000;
        self.rotationPartmlot2.touchRotLimit = Utils.degToRad(Utils.getNoNil(getXMLString(xmlFile, "vehicle.mlot2#touchRotLimit"), 10));
    end




	self.slimak = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.slimak#index"));
	self.slimak2 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.slimak2#index"));	
	
	self.walek = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.walek#index"));
	self.walek2 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.walek2#index"));	

self.mlot = false;
self.test = 300;	

	self.balerParticleSystems = {};
    local psName = "vehicle.balerParticleSystem";
    Utils.loadParticleSystem(xmlFile, self.balerParticleSystems, psName, self.components, false, nil, self.baseDirectory)
    self.balerParticleSystemActive = false;
end;

function Sipma:delete()
 	
    Utils.deleteParticleSystem(self.balerParticleSystems);
	
	if self.balerSound ~= nil then
        delete(self.balerSound);
    end;
end;

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

function Sipma:keyEvent(unicode, sym, modifier, isDown)
	--  if isDown and sym == Input.KEY_n then 
	--	self.rotationMaxzaczep = not self.rotationMaxzaczep;
		--self.isTurnedOn = not self.isTurnedOn;
	--end;
	 if isDown and sym == Input.KEY_b and self.rotationMaxpodbierak == true then 
		
		self.isTurnedOn = not self.isTurnedOn;
	end;
	 if isDown and sym == Input.KEY_n and self.isTurnedOn == false then 
		
		self.rotationMaxpodbierak = not self.rotationMaxpodbierak;
	end;
	
end;

function Sipma:update(dt)


    self.wasToFast = false;
    if self:getIsActive() then
        if self.isTurnedOn and self.rotationMaxpodbierak == true then
			self.rotationMaxklapa = false;
           
		   local toFast = self:doCheckSpeedLimit() and self.lastSpeed*3600 > 25;
            if not toFast then
                local totalArea =0;
                local usedFruitType = FruitUtil.FRUITTYPE_UNKNOWN;
                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);

                    for fruitType,v in pairs(self.fillTypes) do
                        if fruitType ~= FruitUtil.FRUITTYPE_UNKNOWN then
                            local area = Utils.updateFruitWindrowArea(fruitType, x, z, x1, z1, x2, z2, 0)*g_currentMission.windrowCutLongRatio;
                            area = area + Utils.updateFruitCutLongArea(fruitType, x, z, x1, z1, x2, z2, 0);
                            if area > 0 then
                                totalArea = totalArea+area;
                                usedFruitType = fruitType;
                            end;
                        end;
                    end;
                end;

                if totalArea > 0 then
                    local literPerPixel = 4*8000/1200 / 6 / (2*2) *12/4 / 4;

                    local deltaLevel = totalArea * literPerPixel * self.fillScale;

                    -- move all bales
                    local deltaTime = self:getTimeFromLevel(deltaLevel);
                    self:moveBales(deltaTime);

                    local oldFillLevel = self.fillLevel;
                    self:setFillLevel(self.fillLevel+deltaLevel, usedFruitType);
                    if self.fillLevel == self.capacity then
                        local restDeltaFillLevel = deltaLevel - (self.fillLevel-oldFillLevel)
                        self:setFillLevel(restDeltaFillLevel, usedFruitType);
                        -- create bale
                        if self.baleAnimCurve ~= nil and self.baleTypes ~= nil then
                            local baleType = self.baleTypes[usedFruitType];
                            if baleType == nil then
                                baleType = self.defaultBaleType;
                            end;
                            local baleRoot = Utils.loadSharedI3DFile(baleType.filename, self.baseDirectory);

                            local baleId = getChildAt(baleRoot, 0);
                            setRigidBodyType(baleId, "None");
                            link(self.baleAnimRoot, baleId);
                            delete(baleRoot);

                            local bale = {};
                            bale.id = baleId;
                            bale.time = 0;
                            bale.filename = Utils.getFilename(baleType.filename, self.baseDirectory);
                            table.insert(self.bales, bale);

                            self:moveBale(table.getn(self.bales), self:getTimeFromLevel(restDeltaFillLevel));
                        end;
                    end;
                end;
            end;


			
            if not self.balerSoundEnabled and self:getIsActiveForSound() then
                setSamplePitch(self.balerSound, self.balerSoundPitchOffset);
                playSample(self.balerSound, 0, self.balerSoundVolume, 0);
                self.balerSoundEnabled = true;
            end;

            self.wasToFast = toFast;

            if self.lastSpeed*3600 > 3 and not self.balerParticleSystemActive then
                self.balerParticleSystemActive = true;
                Utils.setEmittingState(self.balerParticleSystems, true);
            end;

            if self.lastSpeed*3600 < 3 and self.balerParticleSystemActive then
                self.balerParticleSystemActive = false;
                Utils.setEmittingState(self.balerParticleSystems, false);
            end;

        else

              if self.balerParticleSystemActive then
                self.balerParticleSystemActive = false;
                Utils.setEmittingState(self.balerParticleSystems, false);
            end;
	 end;
        if not self.isTurnedOn and self.balerSoundEnabled then
            stopSample(self.balerSound);
            self.balerSoundEnabled = false;
			self.mlot = false;
		end;
	if not self.isTurnedOn then
		self.rotationMaxklapa = true;
		self.mlot = true;
		end;
	end;

	
		if self.isTurnedOn and self.rotationMaxpodbierak == true then
			rotate(self.slimak, 0.2, 0, 0);
		end;
		if self.isTurnedOn and self.rotationMaxpodbierak == true then
			rotate(self.slimak2, 0.2, 0, 0);
		end;
			if self.isTurnedOn and self.rotationMaxpodbierak == true then
			rotate(self.walek, 0, 0, 0.3);
		end;
		if self.isTurnedOn and self.rotationMaxpodbierak == true then
			rotate(self.walek2, 0, 0, 0.3);
		end; 						
	
if self.rotationPartzaczep ~= nil then
	local x, y, z = getRotation(self.rotationPartzaczep.node);
	local rot = {x,y,z};
	local newRot = Utils.getMovedLimitedValues(rot, self.rotationPartzaczep.maxRot, self.rotationPartzaczep.minRot, 3, self.rotationPartzaczep.rotTime, dt, not self.rotationMaxzaczep);
	setRotation(self.rotationPartzaczep.node, unpack(newRot));
end	
	
if self.rotationPartklapa ~= nil then
	local x, y, z = getRotation(self.rotationPartklapa.node);
	local rot = {x,y,z};
	local newRot = Utils.getMovedLimitedValues(rot, self.rotationPartklapa.maxRot, self.rotationPartklapa.minRot, 3, self.rotationPartklapa.rotTime, dt, not self.rotationMaxklapa);
	setRotation(self.rotationPartklapa.node, unpack(newRot));
end		
	
if self.rotationPartpodbierak ~= nil then
	local x, y, z = getRotation(self.rotationPartpodbierak.node);
	local rot = {x,y,z};
	local newRot = Utils.getMovedLimitedValues(rot, self.rotationPartpodbierak.maxRot, self.rotationPartpodbierak.minRot, 3, self.rotationPartpodbierak.rotTime, dt, not self.rotationMaxpodbierak);
	setRotation(self.rotationPartpodbierak.node, unpack(newRot));
end	
	
	if self.mlot and self.isTurnedOn == true then
		self.test = self.test - dt;
		if self.test < 0 then
			self.rotationMaxmlot = not self.rotationMaxmlot;
			self.rotationMaxmlot2 = not self.rotationMaxmlot2;
			self.test = 300;
		end;

	end;
	
if self.rotationPartmlot ~= nil then
	local x, y, z = getRotation(self.rotationPartmlot.node);
	local rot = {x,y,z};
	local newRot = Utils.getMovedLimitedValues(rot, self.rotationPartmlot.maxRot, self.rotationPartmlot.minRot, 3, self.rotationPartmlot.rotTime, dt, not self.rotationMaxmlot);
	setRotation(self.rotationPartmlot.node, unpack(newRot));
end	
if self.rotationPartmlot2 ~= nil then
	local x, y, z = getRotation(self.rotationPartmlot2.node);
	local rot = {x,y,z};
	local newRot = Utils.getMovedLimitedValues(rot, self.rotationPartmlot2.maxRot, self.rotationPartmlot2.minRot, 3, self.rotationPartmlot2.rotTime, dt, not self.rotationMaxmlot2);
	setRotation(self.rotationPartmlot2.node, unpack(newRot));
end	
	
	
end;

function Sipma:draw()
    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;


	if self.rotationMaxpodbierak then
           g_currentMission:addExtraPrintText("Taste N: Pickup hoch");
    else
          g_currentMission:addExtraPrintText("Taste N: Pickup runter");
    end;

	
	if self.isTurnedOn then
           g_currentMission:addExtraPrintText("Taste B: Ausschalten");
    else
          g_currentMission:addExtraPrintText("Taste B: Einschalten");
    end;

	
end;

function Sipma:onDetach()
    if self.deactivateOnDetach then
        Sipma.onDeactivate(self);
    end;
end;

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

function Sipma:onDeactivate()
    self.wasToFast = false;
    self.isTurnedOn = false;


    if self.balerParticleSystemActive then
        self.balerParticleSystemActive = false;
        Utils.setEmittingState(self.balerParticleSystems, false);
    end;
    Sipma.onDeactivateSounds(self)
end;

function Sipma:onDeactivateSounds()
    if self.balerSoundEnabled then
        stopSample(self.balerSound);
        self.balerSoundEnabled = false;
    end;
end;

function Sipma:getTimeFromLevel(level)
    -- level = capacity -> time = firstBaleMarker
    -- level = 0           -> time = 0
    if self.firstBaleMarker ~= nil then
        return level / self.capacity * self.firstBaleMarker;
    end;
    return 0;
end;

function Sipma:moveBales(dt)
    for i=table.getn(self.bales), 1, -1 do
        self:moveBale(i, dt);
    end;
    self.baleMoveLastTime = self.time
end;

function Sipma:moveBale(i, dt)
    local bale = self.bales[i];
    bale.time = bale.time + dt;
    local v = self.baleAnimCurve:get(bale.time);
    setTranslation(bale.id, v[1], v[2], v[3]);
    setRotation(bale.id, v[4], v[5], v[6]);
    if bale.time >= 1 then
        local deltaRealTime = (self.time - self.baleMoveLastTime)/1000;
        local lx, ly, lz = bale.lastX, bale.lastY, bale.lastZ;
        local x,y,z = getWorldTranslation(bale.id);
        local rx,ry,rz = getWorldRotation(bale.id);
        link(getRootNode(), bale.id);
        g_currentMission:addItemToSave(bale.filename, bale.id, 0);
        setTranslation(bale.id, x, y, z);
        setRotation(bale.id, rx, ry, rz);
        setRigidBodyType(bale.id, "Dynamic");
        setLinearVelocity(bale.id, (x-lx)/deltaRealTime, (y-ly)/deltaRealTime, (z-lz)/deltaRealTime);

        table.remove(self.bales, i);

        -- increase bale count if variable exists (baling mission)
        if g_currentMission.baleCount ~= nil then
            g_currentMission.baleCount = g_currentMission.baleCount + 1;
        end;
    else
        bale.lastX, bale.lastY, bale.lastZ = getWorldTranslation(bale.id);
    end;
end;

function Sipma:allowFillType(fillType)
    return self.fillTypes[fillType] == true;
end;

function Sipma:validateAttacherJoint(implement, jointDesc, dt)
    return true;
end;
