USE `vn`;
DROP procedure IF EXISTS `zone_getOptionsForShipment`;

DELIMITER $$
USE `vn`$$
CREATE DEFINER=`root`@`%` PROCEDURE `zone_getOptionsForShipment`(vShipped DATE)
BEGIN
/**
 * Gets computed options for the passed zones and shipping date.
 *
 * @table tmp.zones(id) The zones ids
 * @param vShipped The shipping date
 * @return tmp.zoneOption(zoneFk, hour, travelingDays, price, bonus, specificity) The computed options
 */
	DROP TEMPORARY TABLE IF EXISTS tLandings;
	CREATE TEMPORARY TABLE tLandings
		(INDEX (eventFk))
		ENGINE = MEMORY
		SELECT e.id eventFk,
				@travelingDays := IFNULL(e.travelingDays, z.travelingDays) travelingDays,
				TIMESTAMPADD(DAY, @travelingDays, vShipped) landed
			FROM tmp.zone t
				JOIN zone z ON z.id = t.id
				JOIN zoneEvent e ON e.zoneFk = t.id;

	DROP TEMPORARY TABLE IF EXISTS tTemp;
	CREATE TEMPORARY TABLE tTemp
		ENGINE = MEMORY
		SELECT t.id zoneFk,
				IFNULL(TIME(e.`hour`), TIME(z.`hour`)) `hour`,
				IFNULL(e.price, z.price) price,
				IFNULL(e.bonus, z.bonus) bonus,
				CASE
					WHEN e.`type` = 'day'
						THEN 1
					WHEN e.`type` = 'range'
						THEN 2
						ELSE 3
				END specificity,
				l.travelingDays,
                l.landed
			FROM tmp.zone t
				JOIN zone z ON z.id = t.id
				JOIN zoneEvent e ON e.zoneFk = t.id
				JOIN tLandings l ON l.eventFk = e.id
			WHERE (
					e.`type` = 'day'
					AND e.`dated` = l.landed
				) OR (
					e.`type` != 'day'
					AND e.weekDays & (1 << WEEKDAY(l.landed))
					AND (e.`started` IS NULL OR l.landed >= e.`started`)
					AND (e.`ended` IS NULL OR l.landed <= e.`ended`)
				);

	DELETE t FROM tTemp t
		JOIN zoneExclusion e
			ON e.zoneFk = t.zoneFk AND e.`dated` = t.landed;

	DROP TEMPORARY TABLE IF EXISTS tmp.zoneOption;
	CREATE TEMPORARY TABLE tmp.zoneOption
		ENGINE = MEMORY
		SELECT *
			FROM (
				SELECT * FROM tTemp
				ORDER BY zoneFk, specificity
			) t
			GROUP BY zoneFk;

	DROP TEMPORARY TABLE
		tTemp,
        tLandings;
END$$

DELIMITER ;

