--
-- InteractiveWindows
-- Specialization for an interactive control
--
-- SFM-Modding
-- @author  Manuel Leithner
-- @date  27/12/09
--

InteractiveWindows = {};

function InteractiveWindows.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(InteractiveControl, specializations);
end;

function InteractiveWindows:load(xmlFile)

	self.windowsCount = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.interactiveComponents.windows#count"), 0);	
	if self.windowsCount ~= 0 then	
		for i=1, self.windowsCount do	
			local windowName = string.format("vehicle.interactiveComponents.windows.window%d", i);				
			local node = Utils.indexToObject(self.components, getXMLString(xmlFile, windowName .. "#index"));
			local name = Utils.getNoNil(g_i18n:getText(getXMLString(xmlFile, windowName .. "#name")), "ERROR");			
			local mark = Utils.indexToObject(self.components, getXMLString(xmlFile, windowName .. "#mark"));
			local highlight = getChildAt(mark, 0);
			local size = Utils.getNoNil(getXMLFloat(xmlFile, windowName .. "#size"), 0.1);
			local animation = {};
			animation.animRootNode = node;
			if animation.animRootNode ~= nil and animation.animRootNode ~= 0 then
				animation.animCharSet = getAnimCharacterSet(animation.animRootNode);
				if animation.animCharSet ~= 0 then
					local clip = getAnimClipIndex(animation.animCharSet, getXMLString(xmlFile, windowName .. "#clip"));
					assignAnimTrackClip(animation.animCharSet, 0, clip);
					setAnimTrackLoopState(animation.animCharSet, 0, false);
					animation.animSpeedScale = Utils.getNoNil(getXMLFloat(xmlFile, windowName .. "#speedScale"), 1);
					animation.animDuration = getAnimClipDuration(animation.animCharSet, clip);
				end;
			end;
			local hydraulic = {};
			hydraulic[1] = {};
			hydraulic[1].node = Utils.indexToObject(self.components, getXMLString(xmlFile, windowName.. "#hydraulic1"));
			if hydraulic[1].node ~= nil then
				hydraulic[1].punch = Utils.indexToObject(self.components, getXMLString(xmlFile, windowName .. "#hydraulicPunch1"));
				hydraulic[1].translationPunch = Utils.indexToObject(self.components, getXMLString(xmlFile, windowName .. "#hydraulicPunchFixPoint1"));
				hydraulic[1].windowFixPoint = Utils.indexToObject(self.components, getXMLString(xmlFile, windowName .. "#windowFixPoint1"));
				local ax, ay, az = getWorldTranslation(hydraulic[1].punch);
				local bx, by, bz = getWorldTranslation(hydraulic[1].translationPunch);
				hydraulic[1].punchDistance = Utils.vector3Length(ax-bx, ay-by, az-bz);
				local xUp, yUp, zUp = Utils.getVectorFromString(getXMLString(xmlFile, windowName.."#vector"));
				if xUp == nil then
					xUp = 0;
					yUp = 1;
					zUp = 1;
				end;
				hydraulic[1].vector = {xUp, yUp, zUp};
				hydraulic[2] = {};
				hydraulic[2].vector = {xUp, yUp, zUp};
				hydraulic[2].node = Utils.indexToObject(self.components, getXMLString(xmlFile, windowName.. "#hydraulic2"));
				if hydraulic[2].node ~= nil then
					hydraulic[2].punch = Utils.indexToObject(self.components, getXMLString(xmlFile, windowName .. "#hydraulicPunch2"));
					hydraulic[2].translationPunch = Utils.indexToObject(self.components, getXMLString(xmlFile, windowName .. "#hydraulicPunchFixPoint2"));
					hydraulic[2].windowFixPoint = Utils.indexToObject(self.components, getXMLString(xmlFile, windowName .. "#windowFixPoint2"));
					ax, ay, az = getWorldTranslation(hydraulic[2].punch);
					bx, by, bz = getWorldTranslation(hydraulic[2].translationPunch);
					hydraulic[2].punchDistance = Utils.vector3Length(ax-bx, ay-by, az-bz);	
				else
					hydraulic[2] = nil;
				end;
			else
				hydraulic = nil;
			end;
			animation.isOpen = false;			
			local window = Window:new(node, highlight, name, animation, mark, size, hydraulic);

			table.insert(self.interactiveObjects, window);
		end;
	end;
	
end;

function InteractiveWindows:delete()
end;

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

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

function InteractiveWindows:update(dt)	
end;

function InteractiveWindows:draw()
end;



--
-- Window Class
-- Specifies an interactive window
--
-- SFM-Modding
-- @author  Manuel Leithner
-- @date  26/12/09
--

Window = {};

function Window:new(node, highlight, name, animation, mark, size, hydraulic)

	local Window_mt = Class(Window, InteractiveComponentInterface);	
    local instance = InteractiveComponentInterface:new(node, highlight, name, mark, size, g_i18n:getText("ic_component_open"), g_i18n:getText("ic_component_close"), Window_mt);

	instance.animation = animation;
	instance.hydraulic = hydraulic;
	instance.lastRotation = {getRotation(instance.node)};
	
	return instance;	
end;


function Window:delete()
	InteractiveComponentInterface.delete(self);
end;

function Window:mouseEvent(posX, posY, isDown, isUp, button)
	InteractiveComponentInterface.mouseEvent(self, posX, posY, isDown, isUp, button);
end;

function Window:keyEvent(unicode, sym, modifier, isDown)
	InteractiveComponentInterface.keyEvent(self, unicode, sym, modifier, isDown);
end;

function Window:update(dt)
	if self.hydraulic ~= nil then
		local x,y,z = getRotation(self.node);
		local a,b,c = unpack(self.lastRotation);
		if math.abs(math.abs(x) - a) > 0.001 or math.abs(math.abs(y) - b) > 0.001 or math.abs(math.abs(z) - c) > 0.001 then
			for k,hydraulic in pairs(self.hydraulic) do	
				local ax, ay, az = getWorldTranslation(hydraulic.node);
				local bx, by, bz = getWorldTranslation(hydraulic.windowFixPoint);
				local dx, dy, dz = worldDirectionToLocal(getParent(hydraulic.node), bx-ax, by-ay, bz-az);												
				setDirection(hydraulic.node, dx, dy, dz, unpack(hydraulic.vector));
				if hydraulic.punch ~= nil then
					local distance = Utils.vector3Length(ax-bx, ay-by, az-bz);
					setTranslation(hydraulic.punch, 0, 0, (distance-hydraulic.punchDistance));
				end;					
			end;
			self.lastRotation = {math.abs(x), math.abs(y), math.abs(z)};
		end;
	end;
	InteractiveComponentInterface.update(self, dt);
end;

function Window:draw()
	InteractiveComponentInterface.draw(self);
end;

function Window:doAction(dt)
	InteractiveComponentInterface.doAction(self,dt);
	local animCharSet = self.animation.animCharSet;
	if self.isOpen then
		if animCharSet ~= 0 then
			if getAnimTrackTime(animCharSet, 0) < 0.0 then
				setAnimTrackTime(animCharSet, 0, 0.0);
			end;
			setAnimTrackSpeedScale(animCharSet, 0, self.animation.animSpeedScale);
			enableAnimTrack(animCharSet, 0);
		end;	
	else
		if animCharSet ~= 0 then
			if getAnimTrackTime(animCharSet, 0) > self.animation.animDuration then
				setAnimTrackTime(animCharSet, 0, self.animation.animDuration);
			end;
			setAnimTrackSpeedScale(animCharSet, 0, -self.animation.animSpeedScale);
			enableAnimTrack(animCharSet, 0);
		end;	
	end;
end;

function Window:onEnter(dt)
	InteractiveComponentInterface.onEnter(self, dt);
end;

function Window:onExit(dt)
	InteractiveComponentInterface.onExit(self, dt);
end;

function Window:setActive()
	InteractiveComponentInterface.setActive(self, isActive);
end;

function Window:setVisible(isVisible)
	InteractiveComponentInterface.setVisible(self, isVisible);
end;