--
-- AnimatedCylinders v1.0
-- Specialization for Animated Cylinders
--
-- @author: 	Milan Lekše (Milan1702976)
-- @date:		17/08/2012
-- @version:	v1.0
--
-- @Usage:
--
--	<AnimatedCylinders>
--		<cylinder girl="0>0|4|0" boy="0>0|4|0|0" ref="0>0|4|0|0|0" target="1>2" />
--	</AnimatedCylinders>
--

AnimatedCylinders = {};

function AnimatedCylinders.prerequisitesPresent(specializations)
    return true
end;

function AnimatedCylinders:load(xmlFile)
	local i=0;
	self.cylinders = {};
	while true do
		local key = string.format("vehicle.AnimatedCylinders.cylinder(%d)",i)
        if not hasXMLProperty(xmlFile, key) then
            break;
        end;
		local girl = Utils.indexToObject( self.components, getXMLString(xmlFile, key.."#girl"));
		local boy = Utils.indexToObject( self.components, getXMLString(xmlFile, key.."#boy"));
		local ref = Utils.indexToObject( self.components, getXMLString(xmlFile, key.."#ref"));
		local target = Utils.indexToObject( self.components, getXMLString(xmlFile, key.."#target"));
		
		local entry = {};
		entry.parts = {};
		entry.rot = {}
		entry.girl = girl;
		entry.rot.x, entry.rot.y, entry.rot.z = getRotation(girl)
		entry.defaultSX, entry.defaultSY, entry.defaultSZ = getScale(girl);
		entry.boy = boy;
		entry.ref = ref;
		entry.target = target;
		local x1, y1, z1 = getWorldTranslation(boy);
		local x2, y2, z2 = getWorldTranslation(ref);
		entry.length2 = Utils.vector3Length(x1-x2, y1-y2, z1-z2);
		local j=0;
		while true do
            local partKey = key..string.format(".part(%d)", j);
			if not hasXMLProperty(xmlFile, partKey) then
				break;
			end;
			local part = {};
			part.node = Utils.indexToObject(self.components, getXMLString(xmlFile, partKey.."#node"));
            table.insert(entry.parts, part);
			j=j+1;
		end
		i=i+1;
		table.insert(self.cylinders, entry);
	end;
	
	local i=0;
	self.parts = {};
	while true do
		local key = string.format("vehicle.AnimatedParts.part(%d)",i)
        if not hasXMLProperty(xmlFile, key) then
            break;
        end;
		local index = Utils.indexToObject( self.components, getXMLString(xmlFile, key.."#index"));
		local ref = Utils.getNoNil(Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#ref")), 0);
		local target = Utils.indexToObject( self.components, getXMLString(xmlFile, key.."#target"));
		local zScale = Utils.getNoNil(getXMLFloat(xmlFile, key.."#zScale"),0)
		
		local entry = {};
		entry.parent = parent;
		entry.index = index;
		entry.defaultSX, entry.defaultSY, entry.defaultSZ = getScale(index);
		entry.target = target;
		entry.zScale = zScale;
		if zScale > 0 then
			entry.ref = target;
		else
			entry.ref = ref;
		end
		local x1, y1, z1 = getWorldTranslation(entry.index);
		local x2, y2, z2 = getWorldTranslation(entry.ref);
		entry.length2 = Utils.vector3Length(x1-x2, y1-y2, z1-z2);
		
		i=i+1;
		table.insert(self.parts, entry);
	end;
end;

function AnimatedCylinders:delete()
end;

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

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

function AnimatedCylinders:readStream(streamId, connection)
end;

function AnimatedCylinders:writeStream(streamId, connection)
end;

function AnimatedCylinders:update(dt)
end;

function AnimatedCylinders:updateTick(dt)
	for i, cylinder in pairs(self.cylinders) do
		setScale(cylinder.girl, cylinder.defaultSX, cylinder.defaultSY, cylinder.defaultSZ)
		local ax, ay, az = getWorldTranslation(cylinder.girl);
		local bx, by, bz = getWorldTranslation(cylinder.target);
		local x, y, z = worldDirectionToLocal(getParent(cylinder.girl), bx-ax, by-ay, bz-az);
		local upX, upY, upZ = 0,1,0;
		-- if math.abs(y) > 0.99*Utils.vector3Length(x, y, z) then
			-- -- direction and up is parallel
			-- upY = 0;
			-- if y > 0 then
				-- upZ = 1;
			-- else
				-- upZ = -1;
			-- end;
		-- end;
		setDirection(cylinder.girl, x, y, z, upX, upY, upZ);
		local distance = Utils.vector3Length(ax-bx, ay-by, az-bz);
		setTranslation(cylinder.boy, 0, 0, distance - cylinder.length2);
		local numParts = table.getn(cylinder.parts)
		if numParts == 1 then
			numParts = 2
		end
		local PartDistance = (distance - cylinder.length2) / numParts
		local NewDistance = 0
		for j, part in pairs(cylinder.parts) do
			NewDistance = NewDistance + PartDistance
			setTranslation(part.node, 0, 0, NewDistance);
		end
	end;
	
	for i, part in pairs(self.parts) do
		setScale(part.index, part.defaultSX, part.defaultSY, part.defaultSZ)
		
		local ax, ay, az = getWorldTranslation(part.index);
		local bx, by, bz = getWorldTranslation(part.target);
		local x, y, z = worldDirectionToLocal(getParent(part.index), bx-ax, by-ay, bz-az);
		
		local upX, upY, upZ = 0,1,0;
		-- if math.abs(y) > 0.99*Utils.vector3Length(x, y, z) then
			-- upY = 0;
			-- if y > 0 then
				-- upZ = 1;
			-- else
				-- upZ = -1;
			-- end;
		-- end;
		setDirection(part.index, x, y, z, upX, upY, upZ);
		if part.zScale > 0 then
			local distance = Utils.vector3Length(ax-bx, ay-by, az-bz);
			setScale(part.index, 1, 1, distance/part.length2);		
		end
	end;
end;

function AnimatedCylinders:draw()	
end;

function AnimatedCylinders:onAttach()
end;

function AnimatedCylinders:onDetach()
end;

function AnimatedCylinders:onLeave()
end;

function AnimatedCylinders:onEnter()
end;