
------------------------------------------------------------------------------
-- 
function CreateTask(...)
    local arg = {...};
    assert(table.getn(arg) == 1);
    local locationName = auxGetLocationName(arg[1]);
	assert(locationName == '' or gameState.zoomZones[locationName] ~= nil);

   	local task = Task(locationName, arg[1], '');

    for i, v in ipairs(arg) do
        if playField:HasObject(v) then
            task:AddObject(v);
        else
            assert(false and "Playfield hasn't an object with this name");
        end
    end
    
    assert(not playField:GetLevelScreen():HasTask(task));

    return task;
end

-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-- 
function auxGetZoomZoneBigestObject(zoomZone)
	assert(zoomZone.objects ~= nil);

    local bigestObject;
    for objName,v in pairs(zoomZone.objects) do
        if (playField:HasObject(objName) == true) then  --// if object hasn't been picked up yet ...
    		local obj = playField:GetObject(objName);
		    local objWidth = obj:GetAnimation():GetWidth();
		    if (bigestObject == nil or objWidth  > bigestObject:GetAnimation():GetWidth() ) then
    			bigestObject = obj;
		    end
	    end
    end

	assert(bigestObject ~= nil);
	return bigestObject;
end

-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-- 
function auxGetZoomZoneByObjectName(objectName)
	assert(gameState ~= nil and gameState.zoomZones ~= nil);

	for i,zone in pairs(gameState.zoomZones) do
		if ( zone.HasObject(objectName) == true ) then
			return zone;
		end
	end
	return nil;
end

-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-- 
function auxGetZoomZoneName(zoomZone)
	assert(gameState ~= nil and gameState.zoomZones ~= nil);

	for i,zone in pairs(gameState.zoomZones) do
		if (zone == zoomZone) then
			return i;
		end
	end
	return '';
end

-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-- 
function GetLocationZone(zone)
   	local isBigLocation = (zone == nil or auxGetZoomZoneBigestObject(zone):GetAnimation():GetWidth() > 640.0);
    if (isBigLocation == true) then
		return zone;
    else
   		return GetLocationZone(zone.parentZoomZone);
   	end
end

-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-- 
function auxGetLocationName(objectName)
	local zoomZone = auxGetZoomZoneByObjectName(objectName);
	return auxGetZoomZoneName(GetLocationZone(zoomZone));
end

------------------------------------------------------------------------------
-- 
function CreatePriorityTask(...)
	local task = CreateTask(unpack(arg));
	task:SetHighPriority(true);
	return task;
end

------------------------------------------------------------------------------
-- 
function CreatePriorityTaskForCube(cubeIndex, ...)
    assert(cubeIndex ~= nil and cubeIndex >= 0 and cubeIndex < CUBE_COUNT);
	local task = CreatePriorityTask(unpack(arg));
	task:SetRequiredCubeIndex(cubeIndex);
	return task;
end

------------------------------------------------------------------------------
-- 
function CLevelScreen:AddTaskSafe(task)
    if task:GetNumberOfObjects() > 0 then
        self:AddTask(task);
    end
end

------------------------------------------------------------------------------
-- 
function AddRandomTasks(sortPriorityObjects, numberToSelect, ...)
    local arg = {...}
    local level_screen = playField:GetLevelScreen();
	local locations = {}
	local locationsCount = 0;

	assert(numberToSelect <= table.getn(arg));

    for i, task in ipairs(arg) do
        --if task:GetNumberOfObjects() > 0 then
		assert(task:GetNumberOfObjects() > 0);
		local locationName = task:GetLocationName();
		if (locations[locationName] == nil) then
			locations[locationName] = {};
		    locations[locationName].random_objects = {};
			locations[locationName].priorityObjects = {};
			locationsCount = locationsCount + 1;
		end

			if task:IsHighPriorityTask() then
	            table.insert(locations[locationName].priorityObjects, task);
			else
	            table.insert(locations[locationName].random_objects, task);
			end
        --end
    end

    --// suffle and add all task of given location
    local ProcessLocation = function(locationName, location)
		local random_objects = location.random_objects;
		local priorityObjects = location.priorityObjects;

	    RandomTableSort(random_objects);
	    if (sortPriorityObjects == true) then
	        RandomTableSort(priorityObjects);
	    end

        assert(numberToSelect % locationsCount == 0);
	    assert(table.getn(random_objects) + table.getn(priorityObjects) >= numberToSelect/locationsCount);

		--// add priority object first and then ...
	    for i = 1, table.getn(priorityObjects), 1 do
	        level_screen:AddTask(priorityObjects[i]);
		end
		--// add misc objects
	    for i = 1, numberToSelect/locationsCount - table.getn(priorityObjects), 1 do
	        level_screen:AddTask(random_objects[i]);
	    end
    end

    local rootLocationName = 'RootZoomZone';
    assert(locations[rootLocationName] ~= nil and "There isn`t root location with name `RootZoomZone`");
    --// process root location first and then the rest of
    ProcessLocation(rootLocationName, locations[rootLocationName]);
	for locationName,location in pairs(locations) do
	    if (locationName ~= rootLocationName) then
	        ProcessLocation(locationName,location);
	    end
	end
end

------------------------------------------------------------------------------
-- 
function CreateToolMap(...)
    local arg = {...};
	local pf = playField;
	local toolObjectList = {};

	if gameState.toolMap == nil then
		gameState.toolMap = {};
	end

    for i, v in ipairs(arg) do
		assert(table.getn(v) == 2);					--// (!) each element must be a vector with 
													--// two objects: toolObject and gameObject 
													--// which this tool is applied to

		assert(pf:HasObject(v[1]) == true and ( pf:HasObject(v[2]) == true or v[2] == ''));
		assert(gameState.toolMap[v[1]] == nil);	--// (!) current tool object there wasn't registered yet

		gameState.toolMap[v[1]] = v[2];
		table.insert(toolObjectList, v[1]);
    end
	SetObjectsToolState(unpack(toolObjectList));
end

-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-- 
function SetObjectsToolState(...)
    local arg = {...};
	local pf = playField;

    for i, v in ipairs(arg) do
        if pf:HasObject(v) then
            local obj = pf:GetObject(v);
            local tools = obj:IsToolObject();
			assert(obj:IsToolObject() == false);

            obj:SetToolState(true);
		else
			assert(false);
        end
    end
end

------------------------------------------------------------------------------
-- 
function SetIconForGameObject(gameObject, resoureFileName)
	local iconAnim = CreateAnimationByPath(resoureFileName);
	local width, height = iconAnim:GetWidth(), iconAnim:GetHeight();
	local hotX, hotY = math.ceil(width/2.0), math.ceil(height/2.0);

	iconAnim:SetHotSpot(hotX, hotY);
	iconAnim:SetBlendMode(2);
	iconAnim:SetColor('0xFFFFFFFF');

	assert(iconAnim);

   	gameObject:SetIcon(iconAnim);
end
