--
-- frontloaderControl
--
-- @author Geri-G
-- @date  12/07/2011 v1.0 LS11
-- @web www.geri-g.de
--
-- Copyright (C) Geri-G, All Rights Reserved.

frontloaderControl = {};
Vehicle.registerJointType("Stollf_FZ_frontloader");
Vehicle.registerJointType("Stollf_FZ_frontloaderTool");

function frontloaderControl.prerequisitesPresent(specializations)
	--print("specialization frontloaderControl v1 by Geri-G");
    return SpecializationUtil.hasSpecialization(Attachable, specializations);
end;

function frontloaderControl:load(xmlFile)
	self.load2 = frontloaderControl.load2;
	self.getAttachableInRange = frontloaderControl.getAttachableInRange;
	--Utils.sharedI3DFiles[self.baseDirectory.."Stoll_FZ80/Stoll_FZ80.i3d"] = nil;
	
	self.setArmSpeed = frontloaderControl.setArmSpeed;
	self.frontladerAnimations = {Utils.getNoNil(getXMLString(xmlFile,"vehicle.frontloader#ArmAnim"), "FRONTLOADER_ARM"),Utils.getNoNil(getXMLString(xmlFile,"vehicle.frontloader#ToolAnim"), "FRONTLOADER_TOOL")};
	self.moveMulti = Utils.getNoNil(getXMLFloat(xmlFile,"vehicle.frontloader#moveMulti"), 0.8);
	local jointDesc = self.attacherJoints[getXMLInt(xmlFile,"vehicle.frontloader#attacherJointIndice")+1];
	self.jointAngle = math.rad(getXMLFloat(xmlFile,"vehicle.frontloader#jointAngle"));

	
	self.frontLoaderToolJoint = {};
	if self.frontLoaderToolJoint ~= nil then
		self.frontLoaderToolJoint = jointDesc;
		self.frontLoaderToolJoint.isFixed = true;
		self.frontLoaderToolJoint.bottomReferenceNode = Utils.indexToObject(self.components, getXMLString(xmlFile,"vehicle.frontloader#bottomReference"));
	end;

	--[[self.FL = {};
	self.FL.linkNode = Utils.indexToObject(self.components, getXMLString(xmlFile,"vehicle.frontloader#linkNode"));
	self.FL.isLinked= false;
	if self.FL.linkNode ~= nil then
		self.FL.oldParent= getParent(self.FL.linkNode);
	end;]]
	
	self.loadVehicleAttachement = false;
	self.wasAttached = false;
	self.hasAttachedTools = false;
	
	--Schlaeuche
	self.Schlaeuche = {};
	self.Schlaeuche.schlaeucheMesh = Utils.indexToObject(self.components, getXMLString(xmlFile,"vehicle.schlaeuche#schlaeucheMesh"));
	if self.Schlaeuche.schlaeucheMesh ~= nil then	
		link(getRootNode(),self.Schlaeuche.schlaeucheMesh);
		setTranslation(self.Schlaeuche.schlaeucheMesh,0,0,0);
		setRotation(self.Schlaeuche.schlaeucheMesh,0,0,0);
	
		local AnimRootNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.schlaeuche#rootNode"));
		self.Schlaeuche.AnimCharSet = 0;
		if AnimRootNode ~= nil and AnimRootNode ~= 0 then
			self.Schlaeuche.AnimCharSet = getAnimCharacterSet(AnimRootNode);
			if self.Schlaeuche.AnimCharSet ~= 0 then
				local clip = getAnimClipIndex(self.Schlaeuche.AnimCharSet, getXMLString(xmlFile, "vehicle.schlaeuche#clip"));
				assignAnimTrackClip(self.Schlaeuche.AnimCharSet, 0, clip);
				setAnimTrackLoopState(self.Schlaeuche.AnimCharSet, 0, false);
				self.Schlaeuche.AnimSpeedScale = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.schlaeuche#speedScale"), 1);
				self.Schlaeuche.AnimDuration = getAnimClipDuration(self.Schlaeuche.AnimCharSet, clip);
			end;
		end;
	end;
	jointDesc = self.frontLoaderToolJoint;
	local x,y,z = getRotation(jointDesc.jointTransform);
	jointDesc.oldJointRot = {x,y,z};
	y = y+math.rad(120);
	jointDesc.NewJointRot = {x,y,z};
	setRotation(jointDesc.jointTransform,unpack(jointDesc.NewJointRot));
	self.atachingforced = false;
end;

function frontloaderControl:readStream(streamId, connection)

end;

function frontloaderControl:writeStream(streamId, connection)

end;
function frontloaderControl:updateTick(dt)
	if self:getIsActive() then
		if self:getAnimationTime(self.frontladerAnimations[1]) <= 0.1 and self.attacherJoints[1].jointIndex ~=0 then
			self.allowsDetaching = true;
		else
			self.allowsDetaching = false;
		end;
	end;
	if self.loadVehicleAttachement == true then
		self.loadVehicleAttachement = false;
		local Vehicleindex = self.wasAttached;
		if Vehicleindex ~= nil and Vehicleindex ~= false and g_currentMission.vehicles[Vehicleindex]~= nil then
			local attachableInMountRange, attachableInMountRangeIndex, attachableInMountRangeVehicle = self:getAttachableInRange(g_currentMission.vehicles[Vehicleindex],1);
			g_currentMission.vehicles[Vehicleindex]:attachImplement(self, attachableInMountRangeIndex);
		end; 
		local hasObjectAttached= self.hasAttachedTools;
		if hasObjectAttached then
			jointDesc = self.frontLoaderToolJoint;
			setRotation(jointDesc.jointTransform,unpack(jointDesc.oldJointRot));
			local attachableInMountRange, attachableInMountRangeIndex, attachableInMountRangeVehicle = self:getAttachableInRange(self,2);
			self.atachingforced = true;
			if attachableInMountRange ~= nil then
				self:attachImplement(attachableInMountRange, attachableInMountRangeIndex);
			end;
		end;
	end;
end;
function frontloaderControl:update(dt)
	if self:getIsActive() then
		if self:getIsActiveForInput() then	
			local move = InputBinding.getDigitalInputAxis(InputBinding.AXIS_FRONTLOADER_ARM);
			if InputBinding.isAxisZero(move) then
				move = InputBinding.getAnalogInputAxis(InputBinding.AXIS_FRONTLOADER_ARM);
			end;

			self:setArmSpeed(1,move);		
			
			local move2 = InputBinding.getDigitalInputAxis(InputBinding.AXIS_FRONTLOADER_TOOL);
			if InputBinding.isAxisZero(move2) then
				move2 = InputBinding.getAnalogInputAxis(InputBinding.AXIS_FRONTLOADER_TOOL);
			end;
			move = move*self.moveMulti;
			self:setArmSpeed(2,move+move2);	

		end;
	else
		--self:setArmSpeed(1,0,true);
		--self:setArmSpeed(2,0,true);
	end;
	if self:getIsActive() and self.isServer then

		if self.frontLoaderToolJoint ~= nil and self.frontLoaderToolJoint.implement~= nil and self.frontLoaderToolJoint.isFixed == false then

			local jointDesc = self.frontLoaderToolJoint;
			local implement = jointDesc.implement;
			local object = implement.object;
			local x1,y1,z1 = getWorldTranslation(jointDesc.bottomReferenceNode);
			local x2,y2,z2 = getWorldTranslation(object.attacherJoint.topReferenceNode);
			local dis = Utils.vector3Length(x1-x2,y1-y2,z1-z2);
			--print("distance: "..dis);
			if dis <= 0.02 then
				setJointRotationLimit(jointDesc.jointIndex,2,true,-0,0); --vectoren !
				self.frontLoaderToolJoint.isFixed = true;
			end;
		end;
	end;
	if self:getIsActive() then
		local animT = self.animations[self.frontladerAnimations[1]];
		if self:getIsAnimationPlaying(self.frontladerAnimations[1])==true and isAnimTrackEnabled(self.Schlaeuche.AnimCharSet,0)==false then
			enableAnimTrack(self.Schlaeuche.AnimCharSet, 0);
			setAnimTrackSpeedScale(self.Schlaeuche.AnimCharSet, 0,animT.currentSpeed);
			setAnimTrackTime(self.Schlaeuche.AnimCharSet, 0, self:getRealAnimationTime(self.frontladerAnimations[1]), true);
		elseif self:getIsAnimationPlaying(self.frontladerAnimations[1])==false and isAnimTrackEnabled(self.Schlaeuche.AnimCharSet,0)==true then

			disableAnimTrack(self.Schlaeuche.AnimCharSet, 0);
		else

		end;
	end;
end;
function frontloaderControl:setArmSpeed(index,speed,noEventSend)
	local anim = self.frontladerAnimations[index];
	local animT = self.animations[anim];
	if math.abs(speed) >= 0.1 then
		if not self:getIsAnimationPlaying(anim) and ( (speed >0 and self:getAnimationTime(anim) <1)or(speed <0 and self:getAnimationTime(anim) >0) ) then
			self:playAnimation(anim, speed, animT.currentTime/animT.duration,noEventSend);
			if index == 1 then
				enableAnimTrack(self.Schlaeuche.AnimCharSet, 0);
				setAnimTrackSpeedScale(self.Schlaeuche.AnimCharSet, 0,speed);
				setAnimTrackTime(self.Schlaeuche.AnimCharSet, 0, self:getRealAnimationTime(anim), true);
			end;
		elseif self:getIsAnimationPlaying(anim) and self:getAnimationTime(anim) <1 and self:getAnimationTime(anim) >0 then
			if math.abs(speed-animT.currentSpeed) >= 0.1 then
				frontloaderControllEvent.sendEvent(self, index, speed,noEventSend)
				self:setAnimationSpeed(anim,speed);
				if index == 1 then
					setAnimTrackSpeedScale(self.Schlaeuche.AnimCharSet, 0, speed);
					setAnimTrackTime(self.Schlaeuche.AnimCharSet, 0, self:getRealAnimationTime(anim), true);
				end;
			end;
		end;
	else
		if self:getIsAnimationPlaying(anim) then
			self:stopAnimation(anim,noEventSend);
			if index == 1 then
				disableAnimTrack(self.Schlaeuche.AnimCharSet, 0);
			end;
		end;
	end;
	return;
end;

function frontloaderControl:draw()

	if (g_currentMission.attachableInMountRange ~= nil and g_currentMission.controlledVehicle.attacherJoints[g_currentMission.attachableInMountRangeIndex].jointIndex == 0) then	
		g_currentMission.hudAttachmentOverlay:render();
		g_currentMission:addHelpButtonText(g_i18n:getText("Attach"), InputBinding.ATTACH);
	end;
end;
function frontloaderControl:onDetach()
	setCenterOfMass(self.components[1].node,self.components[1].centerOfMass[1],self.components[1].centerOfMass[2],self.components[1].centerOfMass[3]+2);

end;

function frontloaderControl:onAttach(attacherVehicle)
	setCenterOfMass(self.components[1].node,unpack(self.components[1].centerOfMass));

end;

function frontloaderControl:delete()
	link(self.components[1].node,self.Schlaeuche.schlaeucheMesh);
	--delete(self.schlaeucheMesh);
end;

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

function frontloaderControl:keyEvent(unicode, sym, modifier, isDown)
end;
function frontloaderControl:getAttachableInRange(vehicle, nearestDistanceSq)
    if vehicle == nil then
        return nil;
    end;
    if nearestDistanceSq == nil then
        nearestDistanceSq = 0.6*0.6;
    end;

    if vehicle ~= nil then
        local nearestAttachable = nil;
        local nearestIndex = 0;
        local nearestVehicle = nil;
        for j=1, table.getn(vehicle.attacherJoints) do
            local jointDesc = vehicle.attacherJoints[j];

            if jointDesc.jointIndex ~= 0 then
                local attached = vehicle.attachedImplements[vehicle:getAttachedIndexFromJointDescIndex(j)].object;
                local a, index, v, d = self:getAttachableInRange(attached, nearestDistanceSq);
                if a ~= nil then
                    nearestDistanceSq = d;
                    nearestVehicle = v;
                    nearestIndex = index;
                    nearestAttachable = a;
                end;
            else
                local px, py, pz = getWorldTranslation(jointDesc.jointTransform);
                for k,attachable in pairs(g_currentMission.attachables) do
                    local attacherJoint = attachable.attacherJoint;
                    if attachable.attacherVehicle == nil and attacherJoint.jointType == jointDesc.jointType then
                        local vx, vy, vz = getWorldTranslation(attacherJoint.node);
                        local distanceSq = Utils.vector2LengthSq(px-vx, pz-vz);
                        local distanceY = math.abs(py-vy);
                        if distanceSq < nearestDistanceSq and distanceY < 1.3 then
							nearestAttachable = attachable;
							nearestDistanceSq = distanceSq;
							nearestIndex = j;
							nearestVehicle = vehicle;
                        end;
                    end;
                end;
            end;
        end;
        return nearestAttachable, nearestIndex, nearestVehicle, nearestDistanceSq;
    end;
    return nil;
end;

function frontloaderControl:attachImplement(implement)
	if implement.object.isStollFZ80Tool and self.isServer   then
		local jointDesc = self.attacherJoints[implement.jointDescIndex];
		setRotation(jointDesc.jointTransform,unpack(jointDesc.oldJointRot));
		setJointFrame(jointDesc.jointIndex, 0, jointDesc.jointTransform);
		if not self.atachingforced then
			setJointRotationLimit(jointDesc.jointIndex,2,true,-math.rad(90),math.rad(90));
			jointDesc.isFixed = false;
		else
			jointDesc.isFixed = true;
		end;
		jointDesc.implement = implement;
		self.atachingforced = false;
	end;
end;
function frontloaderControl:detachImplement(implementIndex)
	if self.attachedImplements[implementIndex] == self.frontLoaderToolJoint.implement then
		self.frontLoaderToolJoint.implement= nil;
		
		jointDesc = self.frontLoaderToolJoint;
		setRotation(jointDesc.jointTransform,unpack(jointDesc.NewJointRot));
	end;
end;
function frontloaderControl:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
	if not resetVehicles then
		self.loadVehicleAttachement = true;
		self.wasAttached = getXMLInt(xmlFile, key.."#attacherVehicle");
		self.hasAttachedTools = getXMLBool(xmlFile, key.."#hasObjectAttached");
		
		for k,v in pairs(self.frontladerAnimations) do
			local animT = self.animations[v];	
			local currentSpeed = getXMLInt(xmlFile, key.."#currentSpeed"..tostring(k));
			if  currentSpeed~= nil then		
				local currentTime = getXMLInt(xmlFile, key.."#currentTime"..tostring(k));		
				self:playAnimation(v, 100, 0,true);
				self:setAnimationStopTime(v,currentTime/animT.duration);
			end;
		end;
	end; 

    return BaseMission.VEHICLE_LOAD_OK;
end;

function frontloaderControl:getSaveAttributesAndNodes(nodeIdent)
	
    local attributes = 'hasObjectAttached="'.. tostring(self.attacherJoints[1].jointIndex >0) ..'"';
	if self.attacherVehicle~=nil then
		local i = 1;
		for k,v in pairs(g_currentMission.vehicles) do			
			if v.isVehicleSaved then	
				if v == self.attacherVehicle then
					attributes = attributes..' attacherVehicle="'.. tostring(i) .. '"';
				end;
				i=i+1;
			end;
		end;
	end;
	for k,v in pairs(self.frontladerAnimations) do
		local animT = self.animations[v];	
		attributes = attributes..' currentSpeed'..tostring(k)..'="'..tostring(animT.currentSpeed) ..'"';
		attributes = attributes..' currentTime'.. tostring(k)..'="'..tostring(animT.currentTime) ..'"';
	end;
    return attributes, nil;
end;