"use strict";
/* Manage a UI for the participation of a person in any thing
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.renderParticipants = renderParticipants;
exports.participationObject = participationObject;
exports.recordParticipation = recordParticipation;
exports.manageParticipation = manageParticipation;
// import { currentUser } from './authn/authn'
const debug = __importStar(require("./debug"));
const rdflib_1 = require("rdflib");
const ns_1 = __importDefault(require("./ns"));
const widgets_1 = require("./widgets");
const utils_1 = require("./utils");
const pad_1 = require("./pad");
const debug_1 = require("./debug");
const style_1 = require("./style");
const styleConstants_1 = __importDefault(require("./styleConstants"));
const solid_logic_1 = require("solid-logic");
class ParticipationTableElement extends HTMLTableElement {
    refresh;
}
const store = solid_logic_1.solidLogicSingleton.store;
/**  Manage participation in this session
*
*  @param {Document} dom - the web page loaded into the browser
*  @param {HTMLTableElement} table - the table element
*  @param {NamedNode} unused1/document - the document to render (this argument is no longer used, but left in for backwards compatibility)
*  @param {NamedNode} subject - the thing in which the participation is happening
*  @param {NamedNode} unused2/me - user that is logged into the pod (this argument is no longer used, but left in for backwards compatibility)
*  @param {ParticipationOptions} options - the options that can be passed in are deleteFunction, link, and draggable; these are used by the personTR button
*/
function renderParticipants(dom, table, unused1, subject, unused2, options) {
    table.setAttribute('style', style_1.style.participantsStyle);
    const newRowForParticipation = function (parp) {
        const person = store.any(parp, ns_1.default.wf('participant'));
        let tr;
        if (!person) {
            tr = dom.createElement('tr');
            tr.textContent = '???'; // Don't crash - invalid part'n entry
            return tr;
        }
        const bg = store.anyValue(parp, ns_1.default.ui('backgroundColor')) || styleConstants_1.default.participationDefaultBackground;
        const block = dom.createElement('div');
        block.setAttribute('style', style_1.style.participantsBlock);
        block.style.backgroundColor = bg;
        tr = (0, widgets_1.personTR)(dom, null, person, options);
        table.appendChild(tr);
        const td = dom.createElement('td');
        td.setAttribute('style', style_1.style.personTableTD);
        td.appendChild(block);
        tr.insertBefore(td, tr.firstChild);
        return tr;
    };
    const syncTable = function () {
        const parps = store.each(subject, ns_1.default.wf('participation')).map(function (parp) {
            (0, debug_1.log)('in participants');
            return [store.anyValue(parp, ns_1.default.cal('dtstart')) || '9999-12-31', parp];
        });
        parps.sort(); // List in order of joining
        const participations = parps.map(function (p) {
            return p[1];
        });
        (0, utils_1.syncTableToArray)(table, participations, newRowForParticipation);
    };
    table.refresh = syncTable;
    syncTable();
    return table;
}
/** Record, or find old, Participation object
 *
 * A participation object is a place to record things specifically about
 * subject and the user, such as preferences, start of membership, etc
 * @param {NamedNode} subject - the thing in which the participation is happening
 * @param {NamedNode} document -  where to record the data
 * @param {NamedNode} me - the logged in user
 *
 */
function participationObject(subject, padDoc, me) {
    return new Promise(function (resolve, reject) {
        if (!me) {
            throw new Error('No user id');
        }
        const parps = store.each(subject, ns_1.default.wf('participation')).filter(function (pn) {
            return store.holds(pn, ns_1.default.wf('participant'), me);
        });
        if (parps.length > 1) { // This can happen. https://github.com/solidos/chat-pane/issues/71
            const candidates = [];
            for (const participation of parps) {
                const date = store.anyValue(participation, ns_1.default.cal('dtstart'));
                if (date) {
                    candidates.push([date, participation]);
                }
            }
            candidates.sort(); // Pick the earliest
            // @@ Possibly, for extra credit, delete the others, if we have write access
            debug.warn('Multiple participation objects, picking earliest, in ' + padDoc);
            resolve(candidates[0][1]);
            // throw new Error('Multiple records of your participation')
        }
        if (parps.length) {
            // If I am not already recorded
            resolve(parps[0]); // returns the participation object
        }
        else {
            const participation = (0, widgets_1.newThing)(padDoc);
            const ins = [
                (0, rdflib_1.st)(subject, ns_1.default.wf('participation'), participation, padDoc),
                (0, rdflib_1.st)(participation, ns_1.default.wf('participant'), me, padDoc),
                (0, rdflib_1.st)(participation, ns_1.default.cal('dtstart'), new Date(), padDoc),
                (0, rdflib_1.st)(participation, ns_1.default.ui('backgroundColor'), (0, pad_1.lightColorHash)(me), padDoc)
            ];
            store.updater.update([], ins, function (uri, ok, errorMessage) {
                if (!ok) {
                    reject(new Error('Error recording your participation: ' + errorMessage));
                }
                else {
                    resolve(participation);
                }
            });
            resolve(participation);
        }
    });
}
/** Record my participation and display participants
 *
 * @param {NamedNode} subject - the thing in which participation is happening
 * @param {NamedNode} padDoc - the document into which the participation should be recorded
 * @param {DOMNode} refreshable - a DOM element whose refresh() is to be called if the change works
 *
 */
function recordParticipation(subject, padDoc, refreshable) {
    const me = solid_logic_1.authn.currentUser();
    if (!me)
        return; // Not logged in
    const parps = store.each(subject, ns_1.default.wf('participation')).filter(function (pn) {
        return store.holds(pn, ns_1.default.wf('participant'), me);
    });
    if (parps.length > 1) {
        throw new Error('Multiple records of your participation');
    }
    if (parps.length) {
        // If I am not already recorded
        return parps[0]; // returns the participation object
    }
    else {
        if (!store.updater.editable(padDoc)) {
            debug.log('Not recording participation, as no write access as ' + me + ' to ' + padDoc);
            return null;
        }
        const participation = (0, widgets_1.newThing)(padDoc);
        const ins = [
            (0, rdflib_1.st)(subject, ns_1.default.wf('participation'), participation, padDoc),
            (0, rdflib_1.st)(participation, ns_1.default.wf('participant'), me, padDoc),
            (0, rdflib_1.st)(participation, ns_1.default.cal('dtstart'), new Date(), padDoc),
            (0, rdflib_1.st)(participation, ns_1.default.ui('backgroundColor'), (0, pad_1.lightColorHash)(me), padDoc)
        ];
        store.updater.update([], ins, function (uri, ok, errorMessage) {
            if (!ok) {
                throw new Error('Error recording your participation: ' + errorMessage);
            }
            if (refreshable && refreshable.refresh) {
                refreshable.refresh();
            }
        });
        return participation;
    }
}
/**  Record my participation and display participants
*
*   @param {Document} dom  - the web page loaded into the browser
*   @param {HTMLDivElement} container - the container element where the participants should be displayed
*   @param {NamedNode} document - the document into which the participation should be shown
*   @param {NamedNode} subject - the thing in which participation is happening
*   @param {NamedNode} me - the logged in user
*   @param {ParticipationOptions} options - the options that can be passed in are deleteFunction, link, and draggable; these are used by the personTR button
*
*/
function manageParticipation(dom, container, padDoc, subject, me, options) {
    const table = dom.createElement('table');
    container.appendChild(table);
    renderParticipants(dom, table, padDoc, subject, me, options);
    let _participation;
    try {
        _participation = recordParticipation(subject, padDoc, table);
    }
    catch (e) {
        container.appendChild((0, widgets_1.errorMessageBlock)(dom, 'Error recording your participation: ' + e)); // Clean up?
    }
    return table;
}
//# sourceMappingURL=participation.js.map