-- Original script: d47 strawmod
-- universal bale ready, fixed unloading, autoload, safe/load trailer state: Bassaddict

ubt = {};

function ubt.prerequisitesPresent(specializations)
	return true;
end;

function ubt:load(xmlFile)
	self.trailerIsEmpty = true;
	self.autoLoad = true;
	self.loadingIsActive = false;
	self.wasToFast = false;
	self.displayHUD = true;
	self.smallBaleMass = 0.13093;
	self.updateCounter = 1;
	self.typeOnTrailer = 1;
	self.ulMode = 4;
	self.numAttacherParts = Utils.getNoNil(getXMLInt(xmlFile,"vehicle.attacherParts#count"), 0);
	self.numAttachers = {};
	self.attacher = {};
	self.attacherLevel = {};
	self.baleType = {};
	for i=1,self.numAttacherParts do
		self.numAttachers[i] = Utils.getNoNil(getXMLInt(xmlFile, string.format("vehicle.Attachers".."%d".."#count",i)), 0);
		self.baleType[i] = {g_i18n:getText(Utils.getNoNil(getXMLString(xmlFile, string.format("vehicle.Attachers".."%d".."#type",i))), "nil"),i};
		self.attacher[i] = {};
		self.attacherLevel[i] = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, string.format("vehicle.Attachers".."%d".."#index",i)));
		for j=1,self.numAttachers[i] do
			self.attacher[i][j] = {};
			local partnamej = string.format("vehicle.Attachers".."%d"..".objectAttacher".."%d",i,j);
			self.attacher[i][j].object = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, partnamej .. "#index"));
			setRigidBodyType(self.attacher[i][j].coll,"NoRigidBody");
			self.attacher[i][j].attachedObject = nil;
			self.attacher[i][j].objectInRange = nil;
		end;
	end;
	self.attachBales = SpecializationUtil.callSpecializationsFunction("attachBales");
	self.setWorkState = SpecializationUtil.callSpecializationsFunction("setWorkState");
	self.balesAttached = SpecializationUtil.callSpecializationsFunction("balesAttached");
    self.fillLMax = self.numAttachers[self.typeOnTrailer];	
	self.Piloni = getXMLString(xmlFile, "vehicle.Piloni#animationName");
	self.PiloniSet = false;
	self.fillL = 0;
	self.fillBall = 0;
	self.PosX = 0.69;
	self.Width = 0.075;
	self.PosY = 0.24;
	self.Height = 0.075;
	self.roundFrame = Utils.getFilename("Huds/round.dds", self.baseDirectory);
	self.roundFrameOverlay = Overlay:new("roundFrameOverlay", self.roundFrame, self.PosX, self.PosY, self.Width, self.Height);
	self.normalFrame = Utils.getFilename("Huds/normal.dds", self.baseDirectory);
	self.normalFrameOverlay = Overlay:new("normalFrameOverlay", self.normalFrame, self.PosX, self.PosY, self.Width, self.Height);
	self.bigFrame = Utils.getFilename("Huds/big.dds", self.baseDirectory);
	self.bigFrameOverlay = Overlay:new("bigFrameOverlay", self.bigFrame, self.PosX, self.PosY, self.Width, self.Height);
	self.hudFrame = Utils.getFilename("Huds/BaleCounter_hud.dds", self.baseDirectory);
	self.hudFrameOverlay = Overlay:new("hudFrameOverlay", self.hudFrame, 0.696, 0.2, 0.055, 0.04);
	self.hudforkFrame = Utils.getFilename("Huds/window.dds", self.baseDirectory);
	self.hudforkFrameOverlay = Overlay:new("hudforkFrameOverlay", self.hudforkFrame, self.PosX, self.PosY, self.Width+0.015, self.Height);
	self.hudtextFrame = Utils.getFilename("Huds/HUD.dds", self.baseDirectory);
	self.hudtextFrameOverlay = Overlay:new("hudtextFrameOverlay", self.hudtextFrame, 0.785, 0.24, 0.20, 0.038);
	self.hud2textFrame = Utils.getFilename("Huds/HUD2.dds", self.baseDirectory);
	self.hud2textFrameOverlay = Overlay:new("hud2textFrameOverlay", self.hud2textFrame, 0.785, 0.24, 0.20, 0.058);
end;

function ubt:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
	if not resetVehicles then
		local tmpTypeonTrailer = getXMLInt(xmlFile, key.."#typeOnTrailer");
		local tmpUlMode = getXMLInt(xmlFile, key.."#ulMode");
		if tmpTypeonTrailer ~= nil then
			self.typeOnTrailer = tmpTypeonTrailer;
			self.fillLMax = self.numAttachers[self.typeOnTrailer];
		end;
		if tmpUlMode ~= nil then
			self.ulMode = tmpUlMode;
		end;
	end;
    return BaseMission.VEHICLE_LOAD_OK;
end;

function ubt:getSaveAttributesAndNodes(nodeIdent)
	local tmpAutoLoad;
	local tmpDisplayHUD;
	if self.autoLoad then
		tmpAutoLoad = "true";
	else
		tmpAutoLoad = "false";
	end;
	if self.displayHUD then
		tmpDisplayHUD = "true";
	else
		tmpDisplayHUD = "false";
	end;
	local attributes = string.format('typeOnTrailer="%d" ulMode="%d" autoLoad="%s" displayHUD="%s"',self.typeOnTrailer,self.ulMode,tmpAutoLoad,tmpDisplayHUD);
	return attributes, nil;
end;

function ubt:delete()
	if (not self.trailerIsEmpty) then
		for i=1, self.numAttachers[self.typeOnTrailer] do
			if self.attacher[self.typeOnTrailer][i].attachedObject ~= nil then
				unlink(self.attacher[self.typeOnTrailer][i].attachedObject);
			end;
		end;
		if self.fillL == 0 then
			self.trailerIsEmpty = true;
		end;
	end;
end;

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

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

function ubt:update(dt)
	if self:getIsActiveForInput() then
		-- bale loading
		if InputBinding.hasEvent(InputBinding.UBT_LOAD) and (not self.autoLoad) and self.balesAttached == false and self.setOpenClose == true then
			for i=1, self.numAttachers[self.typeOnTrailer] do
				if self.attacher[self.typeOnTrailer][i].attachedObject == nil then
					local nearest = ObjectInRangeUbt(self,i);
					if nearest ~= nil then
						self.attacher[self.typeOnTrailer][i].objectInRange = nearest;
						ObjectAttachUbt(self,i);
					else
						break;
					end;
				end;
			end;
		elseif InputBinding.hasEvent(InputBinding.UBT_LOAD) and self.autoLoad and self.balesAttached == false and self.setOpenClose == true then
			if self.loadingIsActive then
				self.loadingIsActive = false;
			else
				self.loadingIsActive = true;
			end;
		end;
		-- bale unloading
		if not self.loadingIsActive then
			for i=1, self.numAttachers[self.typeOnTrailer] do
				if self.attacher[self.typeOnTrailer][i].attachedObject ~= nil then
					ObjectDetachUbt(self,i);
					if i == 1 then
						self:setWorkState(not self.attachBales);
					end;
				end;
			end;
			if self.fillL == 0 then
				self.trailerIsEmpty = true;
			end;
		end;
		-- toggle bale type (big, round, normal, small)
		if InputBinding.hasEvent(InputBinding.UBT_TOGGLE_BALE_TYPE) and self.fillBall == 0 and self.loadingIsActive then
			if self.trailerIsEmpty then
				if self.typeOnTrailer == 7 then
					self.typeOnTrailer = 0;
				end;
				self.typeOnTrailer = self.typeOnTrailer + 1;
				self.fillLMax = self.numAttachers[self.typeOnTrailer];
			end;
		end;
	end;
end;

function ubt:updateTick(dt)
	if self.fillL == 0 then
		self.trailerIsEmpty = true;
	else
		self.trailerIsEmpty = false;
	end;
	self.wasToFast = false;
	if self:getIsActive() then
		if self.fillL == 2 then
			self:playAnimation(self.Piloni, 1);
			self.PiloniSet = true;
		end;
		--stop autoload if trailer is full
		if self.fillL == self.fillLMax then
			self.loadingIsActive = false;
		end;
		-- autoload
		local toFast = self:doCheckSpeedLimit() and self.lastSpeed*3600 > 18;
		if self.autoLoad and self.loadingIsActive then
			if not toFast then
				local i = self.fillL+1;
				if self.attacher[self.typeOnTrailer][i].attachedObject == nil then
					local nearest = ObjectInRangeUbt(self,i);
					if nearest ~= nil then
						self.attacher[self.typeOnTrailer][i].objectInRange = nearest;
						ObjectAttachUbt(self,i);
					end;
				end;
			end;
			self.wasToFast = toFast;
		end;
	end;
end;

function ubt: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.getKeyNamesOfDigitalAction(InputBinding.SPEED_LEVEL2)), 0.07+0.022, 0.019+0.029);
    end;
	setTextAlignment(RenderText.ALIGN_LEFT);
	local xPos = 0.78;
	local yPos = 0.25;
	self.hudforkFrameOverlay:render();
	if self.setOpenClose then
		setTextColor(1,1,1,1);
		setTextBold(true);	
		if (not self.balesAttached and self.loadingIsActive) or (self.balesAttached and self.fillBall > 0) then
			self.hudFrameOverlay:render();
			renderText(xPos-0.08,yPos-0.04,0.02,string.format(" %d / %d",self.fillBall,self.fillLMax));
			if self.typeOnTrailer == 1 then
				self.normalFrameOverlay:render();
			end;
			if self.typeOnTrailer == 2 then
				self.normalFrameOverlay:render();
			end;
			if self.typeOnTrailer == 3 then
				self.normalFrameOverlay:render();
			end;
			if self.typeOnTrailer == 4 then
				self.roundFrameOverlay:render();
			end;
			if self.typeOnTrailer == 5 then
				self.roundFrameOverlay:render();
			end;
			if self.typeOnTrailer == 6 then
				self.bigFrameOverlay:render();
			end;
			if self.typeOnTrailer == 7 then
				self.bigFrameOverlay:render();
			end;
		end;
		local xPos = 0.78+0.01;
		if self.autoLoad then
			if self.loadingIsActive then
				if self.fillBall == 0 then
					self.hud2textFrameOverlay:render();
					renderText(xPos,yPos+0.02,0.02,string.format("%s: "..g_i18n:getText("UBT_TOGGLE_BALE_TYPE"),InputBinding.getKeyNamesOfDigitalAction(InputBinding.UBT_TOGGLE_BALE_TYPE)));
					renderText(xPos,yPos,0.02,string.format("%s: "..g_i18n:getText("UBT_STOP_AUTOLOAD"),InputBinding.getKeyNamesOfDigitalAction(InputBinding.UBT_LOAD)));
				else
					self.hudtextFrameOverlay:render();
					renderText(xPos,yPos,0.02,string.format("%s: "..g_i18n:getText("UBT_STOP_AUTOLOAD"),InputBinding.getKeyNamesOfDigitalAction(InputBinding.UBT_LOAD)));
				end;
			elseif self.fillBall > 0 or self.balesAttached then
				self.hudtextFrameOverlay:render();
				renderText(xPos,yPos,0.02,string.format("%s: "..g_i18n:getText("DETACH_BALES"),InputBinding.getKeyNamesOfDigitalAction(InputBinding.ACTIVE_DEACTIVE)));
			elseif self.fillBall == 0 then
				self.hud2textFrameOverlay:render();
				renderText(xPos,yPos,0.02,string.format("%s: "..g_i18n:getText("UBT_START_AUTOLOAD"),InputBinding.getKeyNamesOfDigitalAction(InputBinding.UBT_LOAD)));
				renderText(xPos,yPos+0.02,0.02,string.format("%s: "..g_i18n:getText("ATTACH_BALES"),InputBinding.getKeyNamesOfDigitalAction(InputBinding.ACTIVE_DEACTIVE)));
			end;
		elseif not self.balesAttached and self.fillBall == 0 then
			self.hudtextFrameOverlay:render();
			renderText(xPos,yPos,0.02,string.format("%s: "..g_i18n:getText("ATTACH_BALES"),InputBinding.getKeyNamesOfDigitalAction(InputBinding.ACTIVE_DEACTIVE)));
		else 
			self.hudtextFrameOverlay:render();
			renderText(xPos,yPos,0.02,string.format("%s: "..g_i18n:getText("DETACH_BALES"),InputBinding.getKeyNamesOfDigitalAction(InputBinding.ACTIVE_DEACTIVE)));
		end;
	end;
end;

function ObjectInRangeUbt(self,k)
	local nearestObject;
	local itemNode;
	local index;
	local nearestDistance = 3;
	local objectCopy = self.attacher[self.typeOnTrailer][k].object;
	local px, py, pz = getWorldTranslation(objectCopy);
	for index, item in pairs(g_currentMission.itemsToSave) do
		itemNode = item.item.nodeId;
		if getParent(item.item.nodeId) == getRootNode() then
			local vx, vy, vz = getWorldTranslation(itemNode);
			local distance = Utils.vector3Length(px-vx, py-vy, pz-vz);
			if distance < nearestDistance then
				local tmpItemMass = getMass(itemNode);
				tmpItemMass = round(tmpItemMass,5);
				if self.baleType[self.typeOnTrailer][1] == g_i18n:getText("BALETYP_BIG") then
					if (getUserAttribute(itemNode, "isStrawbale") or getUserAttribute(itemNode, "isHaybale")) and not (item.item.i3dFilename == "data/maps/models/objects/strawbale/haybaleBaler.i3d" or item.item.i3dFilename == "data/maps/models/objects/strawbale/strawbaleBaler.i3d") and not (tmpItemMass == self.smallBaleMass) then
						index = index;
						nearestObject = itemNode;
						nearestDistance = distance;
					end;
				elseif self.baleType[self.typeOnTrailer][1] == g_i18n:getText("BALETYP_SMALL") then
					if tmpItemMass == self.smallBaleMass then
						index = index;
						nearestObject = itemNode;
						nearestDistance = distance;
					end;
				elseif self.baleType[self.typeOnTrailer][1] == g_i18n:getText("BALETYP_NORMAL") then
					if item.item.i3dFilename == "data/maps/models/objects/strawbale/haybaleBaler.i3d" or item.item.i3dFilename == "data/maps/models/objects/strawbale/strawbaleBaler.i3d" then
						index = index;
						nearestObject = itemNode;
						nearestDistance = distance;
					end;
				elseif self.baleType[self.typeOnTrailer][1] == g_i18n:getText("BALETYP_ROUND") then
					if getUserAttribute(itemNode, "isRoundbale") then
						index = index;
						nearestObject = itemNode;
						nearestDistance = distance;
					end;
				end;
			end;
		end;
	end;
	return nearestObject;
end;

function round(what, precision)
	local tempRes;
	tempRes = math.floor((what*math.pow(10,precision))+0.5) / math.pow(10,precision);
	return tempRes;
end;

function ObjectAttachUbt(self,k)
	setRigidBodyType(self.attacher[self.typeOnTrailer][k].objectInRange,"NoRigidBody");
	local x,y,z = getWorldRotation(self.attacher[self.typeOnTrailer][k].objectInRange);		
	setTranslation(self.attacher[self.typeOnTrailer][k].objectInRange, 0,0,0);
	setRotation(self.attacher[self.typeOnTrailer][k].objectInRange, 0,0,0);
	link(self.attacher[self.typeOnTrailer][k].object,self.attacher[self.typeOnTrailer][k].objectInRange);
	self.attacher[self.typeOnTrailer][k].attachedObject = self.attacher[self.typeOnTrailer][k].objectInRange;
	self.attacher[self.typeOnTrailer][k].objectInRange = nil;
	self.fillL = self.fillL + 1;
	self.fillBall = self.fillBall + 1;
end;

function ObjectDetachUbt(self,k)
	local x,y,z = getWorldTranslation(self.attacher[self.typeOnTrailer][k].attachedObject);
	local rx,ry,rz = getWorldRotation(self.attacher[self.typeOnTrailer][k].attachedObject);
	local root = getRootNode();
	setRigidBodyType(self.attacher[self.typeOnTrailer][k].attachedObject,"Dynamic");
	setTranslation(self.attacher[self.typeOnTrailer][k].attachedObject,x,y,z);
	setRotation(self.attacher[self.typeOnTrailer][k].attachedObject,rx,ry,rz);
	link(root,self.attacher[self.typeOnTrailer][k].attachedObject);
	self.attacher[self.typeOnTrailer][k].attachedObject = nil;
	self.fillL = self.fillL - 1;
end;

function ubt:onAttach()
	self.fillBall = 0;
	self.PiloniSet = false;
	self.fillL = 0;
end;

function ubt:onDetach()
	self.loadingIsActive = false;
	if self.PiloniSet == true then
		self:playAnimation(self.Piloni, -1);
	end;
	self.fillBall = 0;
	self.PiloniSet = false;
	self.fillL = 0;
end;

function ubt:onLeave()
	self.loadingIsActive = false;
end;

function ubt:readStream(streamId, connection)
end;

function ubt:writeStream(streamId, connection)
end;
