--
-- DAbaleConverter
--
--
-- author:    	Xentro (www.ls-uk.info)
-- @version:    v1.0
-- @date:       2012-08-04
-- @history:    v1.0 - inital implementation
-- 
--

baleConv = {};
baleConv.triggerLoaded = false;
baleConv.currentModDirectory = g_currentModDirectory;
baleConv.dbct = {};

addModEventListener(baleConv);

function baleConv:loadMap(name)
    if not baleConv.triggerLoaded then
		print("Doctor Hilti says: if you read this that means you can read the log file... congrats!");
		print("DAbaleConverter.lua was loaded.");
		
        self:loadStates();
        baleConv.triggerLoaded = true;
    end;
end;

function baleConv:deleteMap()
    baleConv.triggerLoaded = false;
end;

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

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

function baleConv:update(dt)
end;

function baleConv:draw()
end;

function baleConv:newTable(trigger)
    table.insert(self.dbct, trigger)
end;

function baleConv:loadStates()
    if g_currentMission.missionInfo.isValid then
        local savegamePath = g_currentMission.missionInfo.savegameDirectory.."/BaleConverter.XML";
        local xmlFile = loadXMLFile("BaleConverter", savegamePath);
		
        local i = 0;
        while true do
            local tag = string.format("BaleConverter.trigger(%d)", i);
			if self.dbct[i+1] == nil or tag == nil then
				break;
			end;
			
			local baleTable = {};
			local k = 0;
			while true do
				local tag2 = tag..string.format(".bale(%d)", k);
				local id = getXMLInt(xmlFile, tag2.."#id");
				local time = Utils.getNoNil(getXMLFloat(xmlFile, tag2.."#time"), 0);
				local deleteTime = Utils.getNoNil(getXMLFloat(xmlFile, tag2.."#deleteTime"), 0);
				local pTime = Utils.getNoNil(getXMLFloat(xmlFile, tag2.."#pTime"), 0);
				local deleted = Utils.getNoNil(getXMLBool(xmlFile, tag2.."#deleted"), true);
				if id == nil or time == nil then
					break;
				end;
				local entry = {};
				entry.id = id;
				entry.time = time;
				entry.deleteTime = deleteTime;
				entry.pTime = pTime;
				entry.deleted = deleted;
				baleTable[id] = entry;
				
				self.dbct[i+1].baleTable[id] = baleTable[id];
				k = k + 1;
			end;
            i = i + 1;
        end;
        delete(xmlFile);
    end;
end;

function baleConv:saveStates()
	local rootTag = "BaleConverter";
	local xmlFile = createXMLFile("BaleConverter", self.savegames[self.selectedIndex].savegameDirectory.."/BaleConverter.XML", rootTag);
	local i = 0;
	for _,v in pairs(baleConv.dbct) do
		local tag = string.format(rootTag..".trigger(%d)", i);
		local k = 0;
		for _,b in pairs(v.baleTable) do
			local tag2 = tag..string.format(".bale(%d)", k);
			setXMLInt(xmlFile, tag2.."#id", b.id);
			setXMLFloat( xmlFile, tag2.."#time", b.time);
			setXMLFloat( xmlFile, tag2.."#deleteTime", b.deleteTime);
			setXMLFloat( xmlFile, tag2.."#pTime", b.pTime);
			setXMLBool( xmlFile, tag2.."#deleted", b.deleted);
			k = k + 1;
		end;
		i = i + 1;
	end;
	saveXMLFile(xmlFile);
	delete(xmlFile);
end;

CareerScreen.saveSelectedGame = Utils.appendedFunction(CareerScreen.saveSelectedGame, baleConv.saveStates);

DAbaleConverter = {};

local DAbaleConverter_mt = Class(DAbaleConverter, Object);

function onCreateDAbaleConverter(self, name)
    local instance = DAbaleConverter:new(g_server ~= nil, g_client ~= nil);
    local index = g_currentMission:addOnCreateLoadedObject(instance);
    instance:load(name);
    instance:register(true);
end;

function DAbaleConverter:new(isServer, isClient)
    local self = Object:new(isServer, isClient, DAbaleConverter_mt);
    self.className = "DAbaleConverter";
    
    return self;
end;

function DAbaleConverter:load(name)    	
	self.triggerId = name;
	addTrigger(name, "triggerCallback", self);
	self.isEnabled = true;
	
	self.test = Utils.getNoNil(getUserAttribute(name, "terrainHelp"), false);
	
	self.baleTable = {};
	
	self.terrainThreshold = Utils.getNoNil(getUserAttribute(name, "terrainThreshold"), 0.2);
	self.baleTime = Utils.getNoNil(getUserAttribute(name, "baleTime"), 9000);
	self.deleteTime = Utils.getNoNil(getUserAttribute(name, "deleteTime"), 0);
	self.particleTime = Utils.getNoNil(getUserAttribute(name, "particleTime"), 300);
	-- self.fillLevel = Utils.getNoNil(getUserAttribute(name, "fillLevel"), 200);
	local fillLevel = getUserAttribute(name, "fillLevel");
	local small, round = Utils.getVectorFromString(fillLevel);
	self.smallBales = Utils.getNoNil(small, 200);
	self.bigBales = self.smallBales * 2; -- Heston bales
	self.roundBales = Utils.getNoNil(round, 500);
	
	local fillType = Utils.getNoNil(getUserAttribute(name, "fillType"), "manure");
	self.fillType = Fillable.fillTypeNameToInt[fillType];
	
	local particlePositionStr = getUserAttribute(name, "particlePosition");
	if particlePositionStr ~= nil then
		local x,y,z = Utils.getVectorFromString(particlePositionStr);
		if x ~= nil and y ~= nil and z ~= nil then
			self.particlePosition = {x,y,z};
		end;
	end;
	
	local particleSystem = getUserAttribute(name, "particleSystem");
	if particleSystem ~= nil then
		-- self.particleSystemRoot = loadI3DFile("data/vehicles/particleSystems/" .. particleSystem .. ".i3d");
		self.particleSystemRoot = loadI3DFile(baleConv.currentModDirectory.."particleSystems/".. particleSystem ..".i3d");
		local x,y,z = getTranslation(name);
		if self.particlePosition ~= nil then
			x = x + self.particlePosition[1];
			y = y + self.particlePosition[2];
			z = z + self.particlePosition[3];
		end;
		setTranslation(self.particleSystemRoot, x,y,z);
		setRotation(self.particleSystemRoot, 0, 0, 180)
		link(getParent(name), self.particleSystemRoot);

		for i=0, getNumOfChildren(self.particleSystemRoot)-1 do
			local child = getChildAt(self.particleSystemRoot, i);
			if getClassName(child) == "Shape" then
				local geometry = getGeometry(child);
				if geometry ~= 0 then
					if getClassName(geometry) == "ParticleSystem" then
						self.particleSystem = geometry;
					end;
				end;
			end;
		end;

		if self.particleSystem ~= nil then
			setEmittingState(self.particleSystem, false);
		end;
		self.particlesActive = false;
	end;
	
	baleConv:newTable(self)
end;

function DAbaleConverter:delete()
	if self.isServer then
		removeTrigger(self.triggerId);
	end;
	
	if self.particleSystemRoot ~= nil then
		delete(self.particleSystemRoot);
	end;
end;

function DAbaleConverter:update(dt)
	for k,v in pairs(self.baleTable) do
		if v ~= nil and v.id ~= nil and v.time ~= nil then
			
			if v.object ~= nil and v.object.nodeId ~= nil and v.object.nodeId > 0 then 
				local x,y,z = getWorldTranslation(v.object.nodeId);
				
				local terrainHeight = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, 0, z);
				if v.test then
					print("bale "..k);
					print("terrainHeight: "..tostring(terrainHeight + self.terrainThreshold));
					print("bale height: "..tostring(y));
					if y > terrainHeight + self.terrainThreshold then
						print("add "..tostring(((terrainHeight + self.terrainThreshold)-y)+0.05).." too terrainThreshold");
						print("too get the best result then push the bale into trigger.");
					else
						print("your terrain height is bigger then the bale and that's good.");
					end;
					v.test = false;
				end;
				
				if y ~= nil and terrainHeight + self.terrainThreshold >= y then
					v.deleteTime = v.deleteTime - dt;
					
					if v.deleteTime <= 0 then
						if self.isServer then
							if self.particleSystemRoot ~= nil then
								setTranslation(self.particleSystemRoot, x, terrainHeight, z);
							end;
							
							v.object:delete();
						end;
						v.deleted = true;
					end;
				end;
			end;
			
			if v.deleted then
				v.time = v.time - dt;
				
				if self.particleSystem ~= nil then
					if v.pTime > 0 then
						v.pTime = v.pTime - dt;
						if not self.particlesActive then
							setEmittingState(self.particleSystem, true);
							self.particlesActive = true;
						end;
					else
						if self.particlesActive then
							setEmittingState(self.particleSystem, false);
							self.particlesActive = false;
						end;
					end;
				end;
				if v.time <= 0 then
					local silo = g_currentMission:getSiloAmount(self.fillType);
					g_currentMission:setSiloAmount(self.fillType, silo + v.fillLevel)
					
					if self.isServer then
						self.baleTable[v.id] = nil;
					end;
				end;
			end;
		end;
	end;
end;

function DAbaleConverter:triggerCallback(triggerId, otherId, onEnter, onLeave, onStay, otherShapeId)
    if self.isEnabled then
		if onEnter then
			local object = g_currentMission:getNodeObject(otherId);
			if object ~= nil and object:isa(Bale) and self.baleTable[otherId] == nil then
				local fillLevel = self.smallBales;
				local splits = Utils.splitString("/", object.i3dFilename);
				if splits[table.getn(splits)]:lower():find("round") ~= nil then
					fillLevel = self.roundBales;
				elseif splits[table.getn(splits)]:lower():find("heston") ~= nil then
					fillLevel = self.bigBales;
				end;
				
				local entry = {};
				entry.id = otherId;
				entry.object = object;
				entry.time = self.baleTime;
				entry.pTime = self.particleTime;
				entry.deleteTime = self.deleteTime;
				entry.deleted = false;
				entry.test = self.test;
				entry.fillLevel = fillLevel;
				self.baleTable[otherId] = entry;
			end;
		elseif onLeave then
			if self.baleTable[otherId] ~= nil then
				self.baleTable[otherId] = nil;
			end;
		end;
	end;
end;