USE provisioning;


DELIMITER ;;
CREATE OR REPLACE PROCEDURE update_sound_set_handle_parents(IN u_sound_set_id INT, IN u_handle_id INT)
BEGIN
    /* declare */
    DECLARE done INT DEFAULT FALSE;


    DECLARE x_set_id INT DEFAULT 0;
    DECLARE x_handle_id INT DEFAULT 0;
    DECLARE x_parent_set_id INT DEFAULT NULL;
    DECLARE x_parent_chain VARCHAR(255) DEFAULT '';


    /* u_sound_set_id and u_handle_id */
    DECLARE x_sound_set_handle CURSOR FOR
        WITH RECURSIVE cte as (
            SELECT v.id AS set_id, v.handle_id,
                       v.id AS data_set_id,
                       CAST('' AS CHAR(4096)) AS parent_chain,
                       CAST(0 as unsigned) AS affected
              FROM (SELECT s.*, h.id as handle_id
                      FROM (voip_sound_sets s, voip_sound_handles h)
                   ) AS v
              LEFT JOIN voip_sound_files f ON f.handle_id = v.handle_id AND f.set_id = v.id
             WHERE v.id = (
                WITH RECURSIVE cte as (
                    SELECT s.id, s.parent_id, CAST(0 as unsigned) as iter
                      FROM voip_sound_sets s
                     WHERE id = u_sound_set_id
                    UNION
                    SELECT s.id, s.parent_id, iter+1 as iter
                      FROM voip_sound_sets s
                      JOIN cte ON cte.parent_id = s.id
                )
                SELECT id
                  FROM cte
                 WHERE iter = (SELECT max(iter) from cte)
             )
               AND v.handle_id = u_handle_id
             UNION
            SELECT v.id AS set_id, v.handle_id,
                   IF(f.use_parent = 0, v.id, cte.data_set_id) AS data_set_id,
                   CONCAT(v.parent_id, IF(LENGTH(cte.parent_chain) > 1, ':', ''), cte.parent_chain) as parent_chain,
                   IF(v.id = u_sound_set_id OR v.parent_id = u_sound_set_id OR affected = 1, 1, 0)
              FROM (SELECT s.*, h.id as handle_id, h.name as handle_name
                    FROM (voip_sound_sets s, voip_sound_handles h)
                   ) AS v
              LEFT JOIN voip_sound_files f ON f.handle_id = v.handle_id AND f.set_id = v.id
              JOIN cte ON cte.set_id = v.parent_id AND cte.handle_id = v.handle_id
        )
        SELECT set_id, handle_id,
               IF(data_set_id = set_id, NULL, data_set_id) as parent_set_id,
               parent_chain
          FROM cte
         WHERE set_id = u_sound_set_id OR affected = 1;


    /* u_sound_set_id */
    DECLARE x_sound_set CURSOR FOR
        WITH RECURSIVE cte as (
            SELECT v.id AS set_id, v.handle_id,
                       v.id AS data_set_id,
                       CAST('' AS CHAR(4096)) AS parent_chain,
                       CAST(0 as unsigned) AS affected
              FROM (SELECT s.*, h.id as handle_id
                      FROM (voip_sound_sets s, voip_sound_handles h)
                   ) AS v
              LEFT JOIN voip_sound_files f ON f.handle_id = v.handle_id AND f.set_id = v.id
             WHERE v.id = (
                WITH RECURSIVE cte as (
                    SELECT s.id, s.parent_id, CAST(0 as unsigned) as iter
                      FROM voip_sound_sets s
                     WHERE id = u_sound_set_id
                    UNION
                    SELECT s.id, s.parent_id, iter+1 as iter
                      FROM voip_sound_sets s
                      JOIN cte ON cte.parent_id = s.id
                )
                SELECT id
                  FROM cte
                 WHERE iter = (SELECT max(iter) from cte)
             )
             UNION
            SELECT v.id AS set_id, v.handle_id,
                   IF(f.use_parent = 0, v.id, cte.data_set_id) AS data_set_id,
                   CONCAT(v.parent_id, IF(LENGTH(cte.parent_chain) > 1, ':', ''), cte.parent_chain) as parent_chain,
                   IF(v.id = u_sound_set_id OR v.parent_id = u_sound_set_id OR affected = 1, 1, 0)
              FROM (SELECT s.*, h.id as handle_id, h.name as handle_name
                    FROM (voip_sound_sets s, voip_sound_handles h)
                   ) AS v
              LEFT JOIN voip_sound_files f ON f.handle_id = v.handle_id AND f.set_id = v.id
              JOIN cte ON cte.set_id = v.parent_id AND cte.handle_id = v.handle_id
        )
        SELECT set_id, handle_id,
               IF(data_set_id = set_id, NULL, data_set_id) as parent_set_id,
               parent_chain
          FROM cte
         WHERE set_id = u_sound_set_id OR affected = 1;



    /* u_handle_id */
    DECLARE x_handle CURSOR FOR
        WITH RECURSIVE cte as (
                SELECT v.id AS set_id, v.handle_id,
                       v.id AS data_set_id,
                       CAST('' AS CHAR(4096)) AS parent_chain
                  FROM (SELECT s.*, h.id as handle_id
                        FROM (voip_sound_sets s, voip_sound_handles h)
                       ) AS v
                  LEFT JOIN voip_sound_files f ON f.handle_id = v.handle_id AND f.set_id = v.id
                 WHERE v.parent_id IS NULL
                   AND v.handle_id = u_handle_id
                 UNION
                SELECT v.id AS set_id, v.handle_id,
                       IF(f.use_parent = 0, v.id, cte.data_set_id) AS data_set_id,
                       CONCAT(v.parent_id, IF(LENGTH(cte.parent_chain) > 1, ':', ''), cte.parent_chain) as parent_chain
                  FROM (SELECT s.*, h.id as handle_id, h.name as handle_name
                        FROM (voip_sound_sets s, voip_sound_handles h)
                       ) AS v
                  LEFT JOIN voip_sound_files f ON f.handle_id = v.handle_id AND f.set_id = v.id
                  JOIN cte ON cte.set_id = v.parent_id AND cte.handle_id = v.handle_id
        )
        SELECT set_id, handle_id,
               IF(data_set_id = set_id, NULL, data_set_id) as parent_set_id,
               parent_chain
          FROM cte;


    /* none */
    DECLARE x CURSOR FOR
        WITH RECURSIVE cte as (
                SELECT v.id AS set_id, v.handle_id,
                       v.id AS data_set_id,
                       CAST('' AS CHAR(4096)) AS parent_chain
                  FROM (SELECT s.*, h.id as handle_id
                        FROM (voip_sound_sets s, voip_sound_handles h)
                       ) AS v
                  LEFT JOIN voip_sound_files f ON f.handle_id = v.handle_id AND f.set_id = v.id
                 WHERE v.parent_id IS NULL
                 UNION
                SELECT v.id AS set_id, v.handle_id,
                       IF(f.use_parent = 0, v.id, cte.data_set_id) AS data_set_id,
                       CONCAT(v.parent_id, IF(LENGTH(cte.parent_chain) > 1, ':', ''), cte.parent_chain) as parent_chain
                  FROM (SELECT s.*, h.id as handle_id, h.name as handle_name
                        FROM (voip_sound_sets s, voip_sound_handles h)
                       ) AS v
                  LEFT JOIN voip_sound_files f ON f.handle_id = v.handle_id AND f.set_id = v.id
                  JOIN cte ON cte.set_id = v.parent_id AND cte.handle_id = v.handle_id
        )
        SELECT set_id, handle_id,
               IF(data_set_id = set_id, NULL, data_set_id) as parent_set_id,
               parent_chain
          FROM cte;


    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE;


    /* code */
    IF u_sound_set_id IS NOT NULL THEN
        DELETE p FROM voip_sound_set_handle_parents p
         WHERE set_id = u_sound_set_id
           AND NOT EXISTS (SELECT id
                             FROM voip_sound_sets
                            WHERE id = u_sound_set_id);

        IF u_handle_id IS NOT NULL THEN
            DELETE p FROM voip_sound_set_handle_parents p
             WHERE set_id IN (
                WITH RECURSIVE cte as (
                    SELECT s.id
                      FROM voip_sound_sets s
                     WHERE id = u_sound_set_id
                    UNION
                    SELECT s.id
                      FROM voip_sound_sets s
                      JOIN cte ON cte.id = s.parent_id
                )
                SELECT id
                  FROM cte
             )
               AND handle_id = u_handle_id;

            OPEN x_sound_set_handle;
            iter: LOOP
                FETCH x_sound_set_handle INTO x_set_id, x_handle_id, x_parent_set_id, x_parent_chain;
                IF done THEN
                    LEAVE iter;
                END IF;
                INSERT INTO voip_sound_set_handle_parents
                    (set_id, handle_id, parent_set_id, parent_chain)
                VALUES
                    (x_set_id, x_handle_id, x_parent_set_id, x_parent_chain);
            END LOOP;
            CLOSE x_sound_set_handle;
        ELSE
            DELETE p FROM voip_sound_set_handle_parents p
             WHERE set_id IN (
                WITH RECURSIVE cte as (
                    SELECT s.id
                      FROM voip_sound_sets s
                     WHERE id = u_sound_set_id
                    UNION
                    SELECT s.id
                      FROM voip_sound_sets s
                      JOIN cte ON cte.id = s.parent_id
                )
                SELECT id
                  FROM cte
             );

            OPEN x_sound_set;
            iter: LOOP
                FETCH x_sound_set INTO x_set_id, x_handle_id, x_parent_set_id, x_parent_chain;
                IF done THEN
                    LEAVE iter;
                END IF;
                INSERT INTO voip_sound_set_handle_parents
                    (set_id, handle_id, parent_set_id, parent_chain)
                VALUES
                    (x_set_id, x_handle_id, x_parent_set_id, x_parent_chain);
            END LOOP;
            CLOSE x_sound_set;
        END IF;
    ELSE
        IF u_handle_id IS NOT NULL THEN
            DELETE FROM voip_sound_set_handle_parents WHERE handle_id = u_handle_id;

            OPEN x_handle;
            iter: LOOP
                FETCH x_handle INTO x_set_id, x_handle_id, x_parent_set_id, x_parent_chain;
                IF done THEN
                    LEAVE iter;
                END IF;
                INSERT INTO voip_sound_set_handle_parents
                    (set_id, handle_id, parent_set_id, parent_chain)
                VALUES
                    (x_set_id, x_handle_id, x_parent_set_id, x_parent_chain);
            END LOOP;
            CLOSE x_handle;
        ELSE
            DELETE FROM voip_sound_set_handle_parents;

            OPEN x;
            iter: LOOP
                FETCH x INTO x_set_id, x_handle_id, x_parent_set_id, x_parent_chain;
                IF done THEN
                    LEAVE iter;
                END IF;
                INSERT INTO voip_sound_set_handle_parents
                    (set_id, handle_id, parent_set_id, parent_chain)
                VALUES
                    (x_set_id, x_handle_id, x_parent_set_id, x_parent_chain);
            END LOOP;
            CLOSE x;
        END IF;
    END IF;

END ;;
DELIMITER ;

