--
-- Lexion770
-- Specialization for Lexion770
--
-- @author  	Manuel Leithner (SFM-Modding)
-- @version 	v1.0
-- @date  		14/12/11
-- @history:	v1.0 - Initial version
-- 10/03/13		Michi77 - small changes for Lexion 550
--
-- free for noncommerical-usage
--

Lexion770 = {};

function Lexion770.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(ChopperSwitcher, specializations);
end;

function Lexion770:load(xmlFile)
	
	self.setChopperWidthState = SpecializationUtil.callSpecializationsFunction("setChopperWidthState");
	self.getNewChopperRot = Lexion770.getNewChopperRot;
	
	self.maxRotTimeBackup = self.maxRotTime;
	self.minRotTimeBackup = self.minRotTime;
	for _, wheel in pairs(self.wheels) do
		wheel.rotMaxBackup = wheel.rotMax;
		wheel.rotMinBackup = wheel.rotMin;
	end;
	
	self.chopperRotatingParts = {};
	self.chopperRotatingParts.rotationParts = {};
	local i = 0;
	while true do
		local key = string.format("vehicle.chopperRotatingParts.rotationPart(%d)", i);
		local node = getXMLString(xmlFile, key .. "#node");
		if node == nil then
			break;
		end;
		local part = {};
		part.node = Utils.indexToObject(self.components, node);
		part.rotSpeed = getXMLFloat(xmlFile, key .. "#speed") * 1000;
		table.insert(self.chopperRotatingParts.rotationParts, part);
		i = i + 1;
	end;
	
	self.chopperRotatingParts.chopperParts = {};
	local i = 0;
	while true do
		local key = string.format("vehicle.chopperRotatingParts.chopperPart(%d)", i);
		local node = getXMLString(xmlFile, key .. "#node");
		if node == nil then
			break;
		end;
		local part = {};
		part.node = Utils.indexToObject(self.components, node);
		part.inverse = Utils.getNoNil(getXMLBool(xmlFile, key .. "#inverse"), false);
		part.states = {};
		part.currentMinRot = nil;
		part.currentMaxRot = nil;
		local j = 0;
		while true do
			local stateKey = string.format(key .. ".state(%d)", j);
			local minRot = getXMLFloat(xmlFile, stateKey .. "#minRot");
			if minRot == nil then
				break;
			end;
			local state = {};
			state.minRot = {math.rad(minRot)};
			if part.currentMinRot == nil then
				part.currentMinRot = {state.minRot[1]};
			end;
			state.maxRot = {math.rad(getXMLInt(xmlFile, stateKey .. "#maxRot"))};
			
			if part.currentMaxRot == nil then
				part.currentMaxRot = {state.maxRot[1]};
			end;
			state.speed = getXMLFloat(xmlFile, stateKey .. "#speed") * 1000;
			state.i18n = getXMLString(xmlFile, stateKey .. "#i18n");
			table.insert(part.states, state);
			j = j + 1;				
		end;		
		table.insert(self.chopperRotatingParts.chopperParts, part);
		i = i + 1;
	end;	
	self.radsPerMS = math.rad(Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.chopperRotatingParts#degreePerSecond"), 5) / 1000);
	self.chopperWidthState = 0;
	self.currentChopperDirection = -1;
	self.numChopperWidthStates = table.getn(self.chopperRotatingParts.chopperParts[1].states);
	self.chopperLeftDirectionTime = self.chopperRotatingParts.chopperParts[1].states[1].speed;
	
	
	
	-- chopper particle system
	self.addChopperParticleSystems = {};
	local i = 0;
	while true do
		local key = string.format("vehicle.addChopperParticleSystems.chopperParticleSystem(%d)", i);
		local t = getXMLString(xmlFile, key .. "#type");
		if t == nil then
			break;
		end;
		local desc = FruitUtil.fruitTypes[t];
		if desc ~= nil then
			local currentPS = {};

			local particleNode = Utils.loadParticleSystem(xmlFile, currentPS, key, self.components, false, "$data/vehicles/particleSystems/threshingChopperParticleSystem.i3d", self.baseDirectory);
			self.addChopperParticleSystems[desc.index] = currentPS;
			if self.addDefaultChopperParticleSystem == nil then
				self.addDefaultChopperParticleSystem = currentPS;
			end;
		end;
		i = i + 1;
	end;
	
	-- chopper dust particle system
	self.chopperDustParticleSystems = {};
	local i = 0;
	while true do
		local key = string.format("vehicle.chopperDustParticleSystems.chopperDustParticleSystem(%d)", i);
		local t = getXMLString(xmlFile, key .. "#type");
		if t == nil then
			break;
		end;
		local desc = FruitUtil.fruitTypes[t];
		if desc ~= nil then
			local currentPS = {};

			local particleNode = Utils.loadParticleSystem(xmlFile, currentPS, key, self.components, false, "$data/vehicles/particleSystems/threshingChopperParticleSystem.i3d", self.baseDirectory);
			self.chopperDustParticleSystems[desc.index] = currentPS;
			if self.defaultChopperDustParticleSystem == nil then
				self.defaultChopperDustParticleSystem = currentPS;
			end;
		end;
		i = i + 1;
	end;	
	
	self.attachedCutter = {};
	
	self.threshingScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.threshingScale#value"), self.threshingScale);
	self.chopperLeftDirection = false;	
	
	self.lastStrawPSState = false;
	self.lastChopperPSState = false;
	self.maxNumRealLights = 3;
	
	self.isSelectable = true;
end;

function Lexion770:delete()
    for k,v in pairs(self.addChopperParticleSystems) do
        Utils.deleteParticleSystem(v);
    end;
	for k,v in pairs(self.chopperDustParticleSystems) do
        Utils.deleteParticleSystem(v);
    end;
end;

function Lexion770:readStream(streamId, connection)
	local state = streamReadInt8(streamId);
	self:setChopperWidthState(state, true);
end;

function Lexion770:writeStream(streamId, connection)
	streamWriteInt8(streamId, self.chopperWidthState);
end;

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

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

function Lexion770:update(dt)
end;

function Lexion770:updateTick(dt)
	if self:getIsActive() then
	
		for key, particle in pairs(self.addChopperParticleSystems) do
			Utils.setEmittingState(particle, Utils.getNoNil(self.chopperParticleSystems[key].isEmitting, false));
		end;
		for key, particle in pairs(self.chopperDustParticleSystems) do
			Utils.setEmittingState(particle, Utils.getNoNil(self.chopperParticleSystems[key].isEmitting, false));
		end;
		
		for _, part in pairs(self.movingParts) do
			Cylindered.updateMovingPart(self,  part);	
		end;
		
		if not self.isStrawActive and self.isThreshing then
			self.chopperLeftDirectionTime = self.chopperLeftDirectionTime - dt;
			
			for _, rotationPart in pairs(self.chopperRotatingParts.rotationParts) do
				rotate(rotationPart.node, 0, dt*rotationPart.rotSpeed, 0);
			end;
		
			for k, chopperPart in pairs(self.chopperRotatingParts.chopperParts) do
				local state = chopperPart.states[self.chopperWidthState+1];
				local x, y, z = getRotation(chopperPart.node);
				local dir = self.chopperLeftDirection;
				if chopperPart.inverse then
					dir = not self.chopperLeftDirection;
				end;
				local newRot = unpack(Utils.getMovedLimitedValues({y}, chopperPart.currentMaxRot, chopperPart.currentMinRot, 1, state.speed, dt, dir));
				setRotation(chopperPart.node, x, newRot, z);				
				chopperPart.currentMinRot[1] = self:getNewChopperRot(chopperPart.currentMinRot[1], state.minRot[1], dt);
				chopperPart.currentMaxRot[1] = self:getNewChopperRot(chopperPart.currentMaxRot[1], state.maxRot[1], dt);
				if k == 1 then
					if self.chopperLeftDirectionTime < 0 then
						self.chopperLeftDirection = not self.chopperLeftDirection;
						self.chopperLeftDirectionTime = state.speed;
					end;
				end;
			end;
		end;
	end;	
end;

function Lexion770:draw()	
end;

function Lexion770:getNewChopperRot(currentRot, newRot, dt)
	if newRot < currentRot then
		return math.max(newRot, currentRot - (dt * self.radsPerMS));
	else
		return math.min(newRot, currentRot + (dt * self.radsPerMS));
	end;
end;

function Lexion770:setChopperWidthState(state, noEventSend)
end;

function Lexion770:detachImplement(implementIndex)
end;

function Lexion770:attachImplement(implement)
end;

function Lexion770:onDeactivate()
    for k,v in pairs(self.addChopperParticleSystems) do
        Utils.setEmittingState(v, false);
    end;
	for k,v in pairs(self.chopperDustParticleSystems) do
        Utils.setEmittingState(v, false);
    end;
end;

function Lexion770:startThreshing()
	if self.numAttachedCutters > 0 then
		self.maxRotTime = self.maxRotTimeBackup / 0.75;
		self.minRotTime = self.minRotTimeBackup / 0.75;
		for _,wheel in pairs(self.wheels) do
			wheel.rotMax = wheel.rotMaxBackup / 0.75;
			wheel.rotMin = wheel.rotMinBackup / 0.75;
		end;
	end;
end;

function Lexion770:stopThreshing()
    for k,v in pairs(self.addChopperParticleSystems) do
        Utils.setEmittingState(v, false);
    end;
	for k,v in pairs(self.chopperDustParticleSystems) do
        Utils.setEmittingState(v, false);
    end;
	self.maxRotTime = self.maxRotTimeBackup;
	self.minRotTime = self.minRotTimeBackup;
	for _,wheel in pairs(self.wheels) do
		wheel.rotMax = wheel.rotMaxBackup;
		wheel.rotMin = wheel.rotMinBackup;
	end;
end;

--
-- ChopperWidthEvent
-- Networkevent for Lexion770
--
-- @author  	Manuel Leithner (SFM-Modding)
-- @version 	v1.0
-- @date  		14/12/11
-- @history:	v1.0 - Initial version
--
ChopperWidthEvent = {};
ChopperWidthEvent_mt = Class(ChopperWidthEvent, Event);

InitEventClass(ChopperWidthEvent, "ChopperWidthEvent");

function ChopperWidthEvent:emptyNew()
    local self = Event:new(ChopperWidthEvent_mt);
    return self;
end;

function ChopperWidthEvent:new(vehicle, state)
    local self = ChopperWidthEvent:emptyNew()
    self.vehicle = vehicle;
	self.state = state;
    return self;
end;

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

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

function ChopperWidthEvent:run(connection)
	self.vehicle:setChopperWidthState(self.state, true);
	if not connection:getIsServer() then
		g_server:broadcastEvent(ChopperWidthEvent:new(self.vehicle, self.state), nil, connection, self.vehicle);
	end;
end;

function ChopperWidthEvent.sendEvent(vehicle, state, noEventSend)
	if noEventSend == nil or noEventSend == false then
		if g_server ~= nil then
			g_server:broadcastEvent(ChopperWidthEvent:new(vehicle, state), nil, nil, vehicle);
		else
			g_client:getServerConnection():sendEvent(ChopperWidthEvent:new(vehicle, state));
		end;
	end;
end;
