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






ubt = {};

function ubt.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(Motorized, specializations);
end;

function ubt:load(xmlFile)

	self.unloadLeft = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.unloadLeft#index"));
	self.unloadRight = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.unloadRight#index"));
	self.unloadBack = Utils.indexToObject(self.rootNode, getXMLString(xmlFile, "vehicle.unloadBack#index"));
	
	self.trailerIsEmpty = true;
	self.autoLoad = false;
	self.autoLoadText = {g_i18n:getText("AUTOLOAD_MANUAL"),g_i18n:getText("AUTOLOAD_AUTOMATIC")};
	self.loadingIsActive = false;
	self.wasToFast = false;
	self.wasToFast = false;
	self.displayHUD = true;
	
	self.smallBaleMass = 0.13093;
	
	self.updateCounter = 1;
	
	self.typeOnTrailer = 1;
	self.ulMode = 1;
	self.ulRef = {{g_i18n:getText("UNLOAD_LEFT"),false,self.unloadLeft},{g_i18n:getText("UNLOAD_BACK"),false,self.unloadBack},{g_i18n:getText("UNLOAD_RIGHT"),false,self.unloadRight},{g_i18n:getText("UNLOAD_TRAILER"),false,0}};	

	
	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.fillLevel = 0;
    self.fillLevelMax = self.numAttachers[self.typeOnTrailer];
end;

function ubt:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
	if not resetVehicles then
		local tmpTypeonTrailer = getXMLInt(xmlFile, key.."#typeOnTrailer");
		local tmpUlMode = getXMLInt(xmlFile, key.."#ulMode");
		local tmpAutoLoad = getXMLBool(xmlFile, key.."#autoLoad");
		local tmpDisplayHUD = getXMLBool(xmlFile, key.."#displayHUD");
		
		if tmpTypeonTrailer ~= nil then
			self.typeOnTrailer = tmpTypeonTrailer;
			self.fillLevelMax = self.numAttachers[self.typeOnTrailer];
		end;
		if tmpUlMode ~= nil then
			self.ulMode = tmpUlMode;
		end;
		if tmpAutoLoad ~= nil then
			self.autoLoad = tmpAutoLoad;
		end;
		if tmpDisplayHUD ~= nil then
			self.displayHUD = tmpDisplayHUD;
		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.fillLevel == 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.ubtATTACH) and (not self.autoLoad) 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.ubtATTACH) and self.autoLoad then
			if self.loadingIsActive then
				self.loadingIsActive = false;
			else
				self.loadingIsActive = true;
			end;
		end;
		
		-- bale unloading
		if InputBinding.hasEvent(InputBinding.ubtDETACH) and not self.loadingIsActive then
			for i=1, self.numAttachers[self.typeOnTrailer] do
				if self.attacher[self.typeOnTrailer][i].attachedObject ~= nil then
					ObjectDetachUbt(self,i);
				end;
			end;
			if self.fillLevel == 0 then
				self.trailerIsEmpty = true;
			end;
		end;

		-- toggle unloading side (left, back, right, trailer)
		if InputBinding.hasEvent(InputBinding.ubtTOGGLEUNLOAD) then
			if self.ulMode == 4 then
				self.ulMode = 0;
			end;
			self.ulMode = self.ulMode + 1;
		end;
		
		-- toggle bale type (big, round, normal, small)
		if InputBinding.hasEvent(InputBinding.ubtTOGGLEBALETYPE) then
			if self.trailerIsEmpty then
				if self.typeOnTrailer == 5 then
					self.typeOnTrailer = 0;
				end;
				self.typeOnTrailer = self.typeOnTrailer + 1;
				self.fillLevelMax = self.numAttachers[self.typeOnTrailer];
			end;
		end;
		
		-- toggle loading type (automatic, manual)
		if InputBinding.hasEvent(InputBinding.ubtTOGGLELOADINGTYPE) then
			if self.autoLoad and (not self.loadingIsActive) then
				self.autoLoad = false;
			else
				self.autoLoad = true;
			end;
		end;
		
		--toggle displaying HUD
		if InputBinding.hasEvent(InputBinding.ubtTOGGLEHUD) then
			if self.displayHUD then
				self.displayHUD = false;
			else
				self.displayHUD = true;
			end;
		end;
	end;
	
end;

function ubt:updateTick(dt)

	if self.fillLevel == 0 then
		self.trailerIsEmpty = true;
	else
		self.trailerIsEmpty = false;
	end;

	self.wasToFast = false;
	if self:getIsActive() then
		
		--stop autoload if trailer is full
		if self.fillLevel == self.fillLevelMax then
			self.loadingIsActive = false;
		end;
		
		-- autoload
		--local toFast = self:doCheckSpeedLimit() and self.motorVehicle.lastSpeed*3600 > 29;
		--if self.autoLoad and self.loadingIsActive then
		--	if not toFast then
		--		local i = self.fillLevel+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_RIGHT);
	local tmpALText;
	if self.autoLoad then
		tmpALText = self.autoLoadText[2];
	else
		tmpALText = self.autoLoadText[1];
	end;
	renderText(0.73,0.03,0.02,string.format("(%d / %d), %s, %s, %s",self.fillLevel,self.fillLevelMax,self.baleType[self.typeOnTrailer][1],self.ulRef[self.ulMode][1],tmpALText));
	
	setTextAlignment(RenderText.ALIGN_LEFT);
	local xPos = 0.75;
	local yPos = 0.25;
	if self.displayHUD then
		if self.autoLoad then
			if self.loadingIsActive then
				renderText(xPos,yPos+0.1,0.02,string.format("%s: "..g_i18n:getText("UBT_STOP_AUTOLOAD"),InputBinding.getKeyNamesOfDigitalAction(InputBinding.ubtATTACH)));
			else
				renderText(xPos,yPos+0.1,0.02,string.format("%s: "..g_i18n:getText("UBT_START_AUTOLOAD"),InputBinding.getKeyNamesOfDigitalAction(InputBinding.ubtATTACH)));
			end;
		else
			renderText(xPos,yPos+0.1,0.02,string.format("%s: "..g_i18n:getText("UBT_LOAD"),InputBinding.getKeyNamesOfDigitalAction(InputBinding.ubtATTACH)));
		end;
		renderText(xPos,yPos+0.08,0.02,string.format("%s: "..g_i18n:getText("UBT_UNLOAD"),InputBinding.getKeyNamesOfDigitalAction(InputBinding.ubtDETACH)));
		renderText(xPos,yPos+0.06,0.02,string.format("%s: "..g_i18n:getText("UBT_TOGGLE_BALE_TYPE"),InputBinding.getKeyNamesOfDigitalAction(InputBinding.ubtTOGGLEBALETYPE)));
		renderText(xPos,yPos+0.04,0.02,string.format("%s: "..g_i18n:getText("UBT_TOGGLE_UNLOAD_SIDE"),InputBinding.getKeyNamesOfDigitalAction(InputBinding.ubtTOGGLEUNLOAD)));
		renderText(xPos,yPos+0.02,0.02,string.format("%s: "..g_i18n:getText("UBT_TOGGLE_LOADING_TYPE"),InputBinding.getKeyNamesOfDigitalAction(InputBinding.ubtTOGGLELOADINGTYPE)));
		renderText(xPos,yPos,0.02,string.format("%s: "..g_i18n:getText("UBT_HUD_HIDE"),InputBinding.getKeyNamesOfDigitalAction(InputBinding.ubtTOGGLEHUD)));
	else
		renderText(xPos,yPos,0.02,string.format("%s: "..g_i18n:getText("UBT_HUD_SHOW"),InputBinding.getKeyNamesOfDigitalAction(InputBinding.ubtTOGGLEHUD)));
	end;
	
end;

function ObjectInRangeUbt(self,k)
	local nearestObject;
	local itemNode;
	local index;
	local nearestDistance = 15;
	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;
				elseif self.baleType[self.typeOnTrailer][1] == g_i18n:getText("WOOLPALLET") then
					if item.item.i3dFilename == "data/maps/models/objects/pallets/woolPallet.i3d" 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.fillLevel = self.fillLevel + 1;

end;

function ObjectDetachUbt(self,k)
	if self.ulRef[self.ulMode][1] == g_i18n:getText("UNLOAD_TRAILER") then
		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.fillLevel = self.fillLevel - 1;
	else
		local x,y,z = getWorldTranslation(self.attacher[self.typeOnTrailer][k].attachedObject);
		local rx,ry,rz = getWorldRotation(self.attacher[self.typeOnTrailer][k].attachedObject);
		local nx,ny,nz = getWorldTranslation(self.attacherLevel[self.typeOnTrailer]);
		local tx,ty,tz = getWorldTranslation(self.ulRef[self.ulMode][3]);
		local x = x + (tx - nx);
		local y = y + (ty - ny);
		local z = z + (tz - nz);
		local tH = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, 0, z);
		local relHeight = ny - tH;
		local root = getRootNode();
		setRigidBodyType(self.attacher[self.typeOnTrailer][k].attachedObject,"Dynamic");
		setTranslation(self.attacher[self.typeOnTrailer][k].attachedObject,x,(y - relHeight),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.fillLevel = self.fillLevel - 1;
	end;
end;

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

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

function ubt:readStream(streamId, connection)
end;

function ubt:writeStream(streamId, connection)   
end;
