
CREATE OR REPLACE FUNCTION checkImageReadACL(imageid int, trusteeid int) RETURNS boolean AS $$
	SELECT bool_or(checkACL(markfolder.id, $2)) 
			OR bool_or(checkACL(printfolder.id, $2))
			OR checkACL(image.ID, $2)
	FROM image
		LEFT OUTER JOIN exercise AS markexercise ON markexercise.mark = image.id 
		LEFT OUTER JOIN folder AS markfolder ON markfolder.id = markexercise.folder
		LEFT OUTER JOIN exercise AS printexercise ON printexercise.print = image.id 
		LEFT OUTER JOIN folder AS printfolder ON printfolder.id = printexercise.folder
	WHERE image.id = $1
	GROUP BY image.id;
$$ LANGUAGE SQL;
CREATE OR REPLACE FUNCTION checkImageReadACL(imageid int) RETURNS boolean AS $$
	SELECT bool_or(checkACL(markfolder.id)) 
			OR bool_or(checkACL(printfolder.id))
			OR checkACL(image.ID)
	FROM image
		LEFT OUTER JOIN exercise AS markexercise ON markexercise.mark = image.id 
		LEFT OUTER JOIN folder AS markfolder ON markfolder.id = markexercise.folder
		LEFT OUTER JOIN exercise AS printexercise ON printexercise.print = image.id 
		LEFT OUTER JOIN folder AS printfolder ON printfolder.id = printexercise.folder
	WHERE image.id = $1
	GROUP BY image.id;
$$ LANGUAGE SQL;

CREATE OR REPLACE FUNCTION checkAssignmentConstraints(pAID int) RETURNS void AS $$
	DECLARE
		i int;
		vid int;
	BEGIN
		SELECT INTO vid id FROM resulttype WHERE short = 'VALIDATED';
		-- At each step (i.e. ANALYSIS, COMPARISON, EVALUATION), a VALIDATED result
		-- (besides not being allowed to be overwritten) may not be anterior to any
		-- CURRENT or AUTOSAVE result - that is, you can't save after you have submitted.
		-- In other words, the latest result saved must be either VALIDATED or no VALIDATED
		-- result must be present at all.
		FOR i IN (SELECT id FROM resultstep ORDER BY id ASC) LOOP
			IF (((SELECT type FROM result WHERE assignment = pAID AND step = i ORDER BY updatedon DESC LIMIT 1) <> vid) AND ((SELECT count(*) FROM result WHERE assignment = pAID AND step = i AND type = vid) > 0)) THEN
				RAISE EXCEPTION 'Assignment (ID=%) integrity error: cannot save to the CURRENT or AUTOSAVE result after the step (ID=%) has been VALIDATED', pAID, i;
			END IF;
		END LOOP;
		-- One cannot save anything without the previous step being validated.
		FOR i IN (SELECT id FROM resultstep ORDER BY id DESC) LOOP
			IF ((i > 1) AND ((SELECT count(*) FROM result WHERE assignment = pAID AND step = i) > 0)) THEN
				IF ((SELECT count(*) FROM result WHERE assignment = pAID AND step = i-1 AND type = vid) = 0) THEN
					RAISE EXCEPTION 'Assignment (ID=%) integrity error: cannot save a result without the previous step being validated', pAID;
				END IF;
			END IF;
		END LOOP;
		RETURN;
	END;
$$ LANGUAGE plpgsql;

-- Assignment progress is measured by the number of VALIDATED results and, if any, the number
-- of intermediate results (i.e. CURRENT/AUTOSAVE)
-- 0: exercise started (assignment created) but no results at all
-- 1: analysis started (i.e. in analysis, CURRENT or AUTOSAVE result present, no VALIDATED)
-- 2: analysis finished (i.e. in analysis, a VALIDATED result)
-- 3: comparison started
-- 4: comparison finished
-- 5: evaluation started
-- 6: evaluation finished
-- Note that due to the fact that the web application saves 2 times upon validation, steps
-- 2 and 3, as well as steps 4 and 5, are the same: we'll never see steps 2 or step 4, because
-- the results are immediately copied into the next result, bumping the step by one.
-- Note that this is done only to help the user: how frustrating it would be if you had to start
-- all over again when submitting a result, and having to start the next step from scratch.
CREATE OR REPLACE FUNCTION getAssignmentStatus(pAID int) RETURNS int AS $$
	DECLARE
		i int;
		vid int;
	BEGIN
		IF (SELECT count(*) FROM assignment WHERE id = pAID) <> 1 THEN
			RAISE EXCEPTION 'No such assignment (ID=%)', pAID;
		END IF;
		SELECT INTO vid id FROM resulttype WHERE short = 'VALIDATED';
		FOR i IN (SELECT id FROM resultstep ORDER BY id DESC) LOOP
			IF (SELECT count(*) FROM result WHERE assignment = pAID AND step = i AND type = vid) > 0 THEN
				RETURN 2*i;
			ELSIF (SELECT count(*) FROM result WHERE assignment = pAID AND step = i) > 0 THEN
				RETURN 2*i-1;
			END IF;
		END LOOP;
		RETURN 0;
	END;
$$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION getAnnotationType(pTextType text) RETURNS int AS $$
	DECLARE
		res int;
	BEGIN
		SELECT INTO res id FROM annotationtype WHERE name = pTextType;
		IF res IS NULL THEN
			INSERT INTO annotationtype(name) VALUES (pTextType) RETURNING id INTO res;
		END IF;
		RETURN res;
	END;
$$ LANGUAGE plpgsql;
