CREATE TABLE changes (
    id INTEGER NOT NULL PRIMARY KEY,
    uuid char(40) NOT NULL DEFAULT '',
    parent_id INTEGER,
    ucount INTEGER NOT NULL DEFAULT 1,
    itime INTEGER NOT NULL
        DEFAULT (strftime('%s','now')),
    mtime INTEGER NOT NULL
        DEFAULT (strftime('%s','now')),
    mtimetz INTEGER NOT NULL
        DEFAULT (strftime('%s','now','localtime') - strftime('%s','now')),
    mtimetzhm VARCHAR, -- NOT NULL
    path VARCHAR,
    identity_id INTEGER NOT NULL DEFAULT -1,
    author VARCHAR(255) NOT NULL,
    author_contact VARCHAR(255) NOT NULL,
    author_contact_method VARCHAR(255) NOT NULL,
    author_shortname VARCHAR(255) NOT NULL,
    action VARCHAR NOT NULL DEFAULT '',
    action_format VARCHAR NOT NULL DEFAULT '',
    action_topic_id_1 INTEGER,
    action_topic_id_2 INTEGER,
    lang VARCHAR(8) NOT NULL DEFAULT 'en',
    message VARCHAR NOT NULL DEFAULT '',
    yaml VARCHAR NOT NULL,
    valid BOOLEAN DEFAULT 0,
    FOREIGN KEY(identity_id) REFERENCES identities(id)
        ON DELETE CASCADE
        DEFERRABLE INITIALLY DEFERRED,
    FOREIGN KEY(parent_id) REFERENCES changes(id)
        ON DELETE CASCADE,
    FOREIGN KEY(action_topic_id_1) REFERENCES topics(id)
        ON DELETE CASCADE,
    FOREIGN KEY(action_topic_id_2) REFERENCES topics(id)
        ON DELETE CASCADE
);

SELECT create_sequence('changes');
SELECT create_sequence('deltas');


CREATE UNIQUE INDEX
    changes_uuid
ON
    changes(uuid)
WHERE
    uuid != ''
;

CREATE INDEX
    changes_invalid
ON
    changes(valid)
WHERE
    valid = 0
;


CREATE TRIGGER
    changes_ai_1
AFTER INSERT ON
    changes
FOR EACH ROW
BEGIN

    SELECT debug(
        NEW.id,
        NEW.parent_id,
        NEW.identity_id,
        NEW.author,
        NEW.author_contact,
        NEW.author_contact_method,
        NEW.author_shortname,
        NEW.lang,
        NEW.mtime,
        NEW.mtimetz,
        NEW.uuid
    );


    /*
     Insert a matching row in changes_tree where both parent and child
     are set to the id of the newly inserted object. Depth is set to 0
     as both child and parent are on the same level.
     */

    INSERT INTO
        changes_tree (
            parent,
            child,
            depth
        )
    VALUES (
        NEW.id,
        NEW.id,
        0
    );

    /*
     Copy all rows that our parent had as its parents, but we modify
     the child id in these rows to be the id of currently inserted row,
     and increase depth by one.
     */

    INSERT INTO
        changes_tree (
            parent,
            child,
            depth
        )
    SELECT
        x.parent,
        NEW.id,
        x.depth + 1
    FROM
        changes_tree x
    WHERE
        x.child = NEW.parent_id
    ;

END;

CREATE TRIGGER
    changes_bu_4
BEFORE UPDATE OF
    uuid
ON
    changes
FOR EACH ROW WHEN
    OLD.uuid != ''
BEGIN

    SELECT debug(
        OLD.id,
        OLD.uuid
    );

    SELECT RAISE (ABORT, 'changes.uuid is immutable!');
END;


CREATE TRIGGER
    changes_bu_3
BEFORE UPDATE OF
    action,
    action_format,
    action_topic_id_1,
    action_topic_id_2,
    identity_id,
    message
ON
    changes
FOR EACH ROW WHEN
    OLD.action != '' OR
    OLD.action_format != '' OR
    OLD.action_topic_id_1 IS NOT NULL OR
    OLD.action_topic_id_2 IS NOT NULL OR
    (NEW.identity_id != OLD.identity_id AND OLD.identity_id != -1) OR
    OLD.message != ''
BEGIN

    SELECT debug(
        OLD.id,             NEW.id, x'0A',
        OLD.action,  NEW.action, x'0A',
        OLD.action_format,  NEW.action_format, x'0A',
        OLD.action_topic_id_1,  NEW.action_topic_id_1, x'0A',
        OLD.action_topic_id_2,  NEW.action_topic_id_2, x'0A',
        OLD.identity_id,          NEW.identity_id, x'0A',
        OLD.message,     NEW.message, x'0A'
    );

    SELECT RAISE (ABORT, 'Changes are immutable!');
END;

CREATE TRIGGER
    changes_bu_2
BEFORE UPDATE OF
    id, parent_id, mtime, mtimetz, author, author_contact,
    author_contact_method, author_shortname, lang
ON
    changes
FOR EACH ROW
BEGIN

    SELECT debug(
        OLD.id, NEW.id,
        OLD.parent_id, NEW.parent_id, x'0A',
        OLD.mtime,     NEW.mtime, x'0A',
        OLD.mtime,     NEW.mtime, x'0A',
        OLD.mtimetz,   NEW.mtimetz, x'0A',
        OLD.author,    NEW.author, x'0A',
        OLD.author_contact,    NEW.author_contact, x'0A',
        OLD.author_contact_method,    NEW.author_contact_method, x'0A',
        OLD.author_shortname,    NEW.author_shortname, x'0A',
        OLD.lang,      NEW.lang, x'0A'
    );

    SELECT RAISE (ABORT, 'Changes are immutable!');
END;


CREATE TRIGGER
    changes_au_2
AFTER UPDATE OF
    uuid
ON
    changes
FOR EACH ROW WHEN
    NEW.valid = 1
BEGIN

    /*
        The following changes the hub_related_changes_merkle table
    */

    UPDATE
        hub_related_changes
    SET
        merkled = 1
    WHERE
        change_id = NEW.id AND merkled = 0
    ;

    /*
        The following changes the project_related_changes_merkle table
    */

    UPDATE
        project_related_changes
    SET
        merkled = 1
    WHERE
        change_id = NEW.id AND merkled = 0
    ;

END;


CREATE TRIGGER
    changes_au_1
AFTER UPDATE OF
    uuid
ON
    changes
FOR EACH ROW
BEGIN

    SELECT debug(
        NEW.id,
        NEW.uuid
    );

    UPDATE
        changes
    SET
        path =
            CASE WHEN
                NEW.parent_id IS NOT NULL
            THEN
                (SELECT
                    path
                 FROM
                    changes
                 WHERE
                    id = NEW.parent_id
                )
                || '/'
                || strftime('%Y%j%H%M%S',mtime,'unixepoch')
                || substr(NEW.uuid,1,2)
            ELSE
                strftime('%Y%j%H%M%S',mtime,'unixepoch')
                || substr(NEW.uuid,1,2)
            END
    WHERE
        id = NEW.id
    ;


END;


CREATE TRIGGER
    changes_bd_1
BEFORE DELETE ON
    changes
FOR EACH ROW
BEGIN
    select debug(
        OLD.id
    );

    UPDATE
        project_related_changes
    SET
        merkled = 0
    WHERE
        change_id = OLD.id
    ;

END;

