"use strict";

function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.schedulePane = void 0;
var UI = _interopRequireWildcard(require("solid-ui"));
var _solidLogic = require("solid-logic");
var _formsForSchedule = _interopRequireDefault(require("./formsForSchedule.js"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
/*   Scheduler Pane
 **
 **
 */
/* global alert */

var $rdf = UI.rdf;
var ns = UI.ns;
// @@ Give other combos too-- see schedule ontology
var possibleAvailabilities = [ns.sched('No'), ns.sched('Maybe'), ns.sched('Yes')];
var schedulePane = exports.schedulePane = {
  icon: UI.icons.iconBase + 'noun_346777.svg',
  // @@ better?

  name: 'schedule',
  audience: [ns.solid('PowerUser')],
  // Does the subject deserve an Scheduler pane?
  label: function label(subject, context) {
    var kb = context.session.store;
    var t = kb.findTypeURIs(subject);
    if (t['http://www.w3.org/ns/pim/schedule#SchedulableEvent']) {
      return 'Scheduling poll';
    }
    return null; // No under other circumstances
  },
  //  Mint a new Schedule poll
  mintClass: ns.sched('SchedulableEvent'),
  mintNew: function mintNew(context, options) {
    return new Promise(function (resolve, reject) {
      var ns = UI.ns;
      var kb = context.session.store;
      var newBase = options.newBase;
      var thisInstance = options.useExisting || $rdf.sym(options.newBase + 'index.ttl#this');
      var complainIfBad = function complainIfBad(ok, body) {
        if (ok) return;
        console.log('Error in Schedule Pane: Error constructing new scheduler: ' + body);
        reject(new Error(body));
      };

      // ////////////////////// Accesss control

      // Two constiations of ACL for this app, public read and public read/write
      // In all cases owner has read write control

      var genACLtext = function genACLtext(docURI, aclURI, allWrite) {
        var g = $rdf.graph();
        var auth = $rdf.Namespace('http://www.w3.org/ns/auth/acl#');
        var a = g.sym(aclURI + '#a1');
        var acl = g.sym(aclURI);
        var doc = g.sym(docURI);
        g.add(a, UI.ns.rdf('type'), auth('Authorization'), acl);
        g.add(a, auth('accessTo'), doc, acl);
        g.add(a, auth('agent'), me, acl);
        g.add(a, auth('mode'), auth('Read'), acl);
        g.add(a, auth('mode'), auth('Write'), acl);
        g.add(a, auth('mode'), auth('Control'), acl);
        a = g.sym(aclURI + '#a2');
        g.add(a, UI.ns.rdf('type'), auth('Authorization'), acl);
        g.add(a, auth('accessTo'), doc, acl);
        g.add(a, auth('agentClass'), ns.foaf('Agent'), acl);
        g.add(a, auth('mode'), auth('Read'), acl);
        if (allWrite) {
          g.add(a, auth('mode'), auth('Write'), acl);
        }
        return $rdf.serialize(acl, g, aclURI, 'text/turtle');
      };

      /*
          const setACL3 = function (docURI, allWrite, callbackFunction) {
            const aclText = genACLtext(docURI, aclDoc.uri, allWrite)
            return UI.acl.setACL(docURI, aclText, callbackFunction)
          }
          */

      var setACL2 = function setACL2(docURI, allWrite, callbackFunction) {
        var aclDoc = kb.any(kb.sym(docURI), kb.sym('http://www.iana.org/assignments/link-relations/acl')); // @@ check that this get set by web.js

        if (aclDoc) {
          // Great we already know where it is
          var aclText = genACLtext(docURI, aclDoc.uri, allWrite);
          return fetcher.webOperation('PUT', aclDoc.uri, {
            data: aclText,
            contentType: 'text/turtle'
          }).then(function (_result) {
            return callbackFunction(true);
          })["catch"](function (err) {
            callbackFunction(false, err.message);
          });
        } else {
          return fetcher.load(docURI)["catch"](function (err) {
            callbackFunction(false, 'Getting headers for ACL: ' + err);
          }).then(function () {
            var aclDoc = kb.any(kb.sym(docURI), kb.sym('http://www.iana.org/assignments/link-relations/acl'));
            if (!aclDoc) {
              // complainIfBad(false, "No Link rel=ACL header for " + docURI)
              throw new Error('No Link rel=ACL header for ' + docURI);
            }
            var aclText = genACLtext(docURI, aclDoc.uri, allWrite);
            return fetcher.webOperation('PUT', aclDoc.uri, {
              data: aclText,
              contentType: 'text/turtle'
            });
          }).then(function (_result) {
            return callbackFunction(true);
          })["catch"](function (err) {
            callbackFunction(false, err.message);
          });
        }
      };

      // Body of mintNew
      var fetcher = kb.fetcher;
      var updater = kb.updater;
      var me = options.me || _solidLogic.authn.currentUser();
      if (!me) {
        console.log('MUST BE LOGGED IN');
        alert('NOT LOGGED IN');
        return;
      }
      var base = thisInstance.dir().uri;
      var newDetailsDoc, newInstance; // , newIndexDoc

      if (options.useExisting) {
        newInstance = options.useExisting;
        newBase = thisInstance.dir().uri;
        newDetailsDoc = newInstance.doc();
        // newIndexDoc = null
        if (options.newBase) {
          throw new Error('mint new scheduler: Illegal - have both new base and existing event');
        }
      } else {
        newDetailsDoc = kb.sym(newBase + 'details.ttl');
        // newIndexDoc = kb.sym(newBase + 'index.html')
        newInstance = kb.sym(newDetailsDoc.uri + '#event');
      }
      var newResultsDoc = kb.sym(newBase + 'results.ttl');
      var toBeCopied = options.noIndexHTML ? {} : [{
        local: 'index.html',
        contentType: 'text/html'
      }];
      var agenda = [];

      //   @@ This needs some form of visible progress bar
      for (var f = 0; f < toBeCopied.length; f++) {
        var item = toBeCopied[f];
        var fun = function copyItem(item) {
          agenda.push(function () {
            var newURI = newBase + item.local;
            console.log('Copying ' + base + item.local + ' to ' + newURI);
            var setThatACL = function setThatACL() {
              setACL2(newURI, false, function (ok, message) {
                if (!ok) {
                  complainIfBad(ok, 'FAILED to set ACL ' + newURI + ' : ' + message);
                  console.log('FAILED to set ACL ' + newURI + ' : ' + message);
                } else {
                  agenda.shift()(); // beware too much nesting
                }
              });
            };
            kb.fetcher.webCopy(base + item.local, newBase + item.local, item.contentType).then(function () {
              return _solidLogic.authn.checkUser();
            }).then(function (webId) {
              me = webId;
              setThatACL();
            })["catch"](function (err) {
              console.log('FAILED to copy ' + base + item.local + ' : ' + err.message);
              complainIfBad(false, 'FAILED to copy ' + base + item.local + ' : ' + err.message);
            });
          });
        };
        fun(item);
      }
      agenda.push(function createDetailsFile() {
        kb.add(newInstance, ns.rdf('type'), ns.sched('SchedulableEvent'), newDetailsDoc);
        if (me) {
          kb.add(newInstance, ns.dc('author'), me, newDetailsDoc); // Who is sending the invitation?
          kb.add(newInstance, ns.foaf('maker'), me, newDetailsDoc); // Uneditable - wh is allowed to edit this?
        }
        kb.add(newInstance, ns.dc('created'), new Date(), newDetailsDoc);
        kb.add(newInstance, ns.sched('resultsDocument'), newDetailsDoc);
        updater.put(newDetailsDoc, kb.statementsMatching(undefined, undefined, undefined, newDetailsDoc), 'text/turtle', function (uri2, ok, message) {
          if (ok) {
            agenda.shift()();
          } else {
            complainIfBad(ok, 'FAILED to save new scheduler at: ' + newDetailsDoc + ' : ' + message);
            console.log('FAILED to save new scheduler at: ' + newDetailsDoc + ' : ' + message);
          }
        });
      });
      agenda.push(function () {
        kb.fetcher.webOperation('PUT', newResultsDoc.uri, {
          data: '',
          contentType: 'text/turtle'
        }).then(function () {
          agenda.shift()();
        })["catch"](function (err) {
          complainIfBad(false, 'Failed to initialize empty results file: ' + err.message);
        });
      });
      agenda.push(function () {
        setACL2(newResultsDoc.uri, true, function (ok, body) {
          complainIfBad(ok, 'Failed to set Read-Write ACL on results file: ' + body);
          if (ok) agenda.shift()();
        });
      });
      agenda.push(function () {
        setACL2(newDetailsDoc.uri, false, function (ok, body) {
          complainIfBad(ok, 'Failed to set read ACL on configuration file: ' + body);
          if (ok) agenda.shift()();
        });
      });
      agenda.push(function () {
        // give the user links to the new app
        console.log('Finished minting new scheduler');
        options.newInstance = newInstance;
        resolve(options);
      });
      agenda.shift()();
      // Created new data files.
    }); // promise
  },
  // mintNew

  //  Render one meeting schedule poll
  render: function render(subject, context) {
    var dom = context.dom;
    var kb = context.session.store;
    var ns = UI.ns;
    var invitation = subject;
    var appPathSegment = 'app-when-can-we.w3.org'; // how to allocate this string and connect to

    // ////////////////////////////////////////////

    var fetcher = kb.fetcher;
    var updater = kb.updater;
    var waitingForLogin = false;
    var thisInstance = subject;
    var detailsDoc = subject.doc();
    var baseDir = detailsDoc.dir();
    var base = baseDir.uri;
    var resultsDoc = $rdf.sym(base + 'results.ttl');
    // const formsURI = base + 'forms.ttl'
    // We can't in fact host stuff from there because of CORS
    var formsURI = 'https://solidos.github.io/solid-panes/schedule/formsForSchedule.ttl';
    var form1 = kb.sym(formsURI + '#form1');
    var form2 = kb.sym(formsURI + '#form2');
    var form3 = kb.sym(formsURI + '#form3');
    $rdf.parse(_formsForSchedule["default"], kb, formsURI, 'text/turtle'); // Load forms directly

    var inputStyle = 'background-color: #eef; padding: 0.5em;  border: .5em solid white; font-size: 100%'; //  font-size: 120%
    var buttonIconStyle = 'width: 1.8em; height: 1.8em;';

    // Utility functions

    var complainIfBad = function complainIfBad(ok, message) {
      if (!ok) {
        div.appendChild(UI.widgets.errorMessageBlock(dom, message, 'pink'));
      }
    };
    var clearElement = function clearElement(ele) {
      while (ele.firstChild) {
        ele.removeChild(ele.firstChild);
      }
      return ele;
    };
    var refreshCellColor = function refreshCellColor(cell, value) {
      var bg = kb.any(value, UI.ns.ui('backgroundColor'));
      if (bg) {
        cell.setAttribute('style', 'padding: 0.3em; text-align: center; background-color: ' + bg + ';');
      }
    };
    var me;
    _solidLogic.authn.checkUser().then(function (webId) {
      me = webId;
      if (logInOutButton) {
        logInOutButton.refresh();
      }
      if (webId && waitingForLogin) {
        waitingForLogin = false;
        showAppropriateDisplay();
      }
    });
    console.log('me: ' + me); // @@ curently not actually used elsewhere

    // //////////////////////////////  Reproduction: spawn a new instance
    //
    // Viral growth path: user of app decides to make another instance
    //

    var newInstanceButton = function newInstanceButton() {
      var b = UI.login.newAppInstance(dom, {
        noun: 'scheduler'
      }, initializeNewInstanceInWorkspace);
      b.firstChild.setAttribute('style', inputStyle);
      return b;
    }; // newInstanceButton

    // ///////////////////////  Create new document files for new instance of app

    var initializeNewInstanceInWorkspace = function initializeNewInstanceInWorkspace(ws) {
      var newBase = kb.any(ws, ns.space('uriPrefix'));
      if (!newBase) {
        newBase = ws.uri.split('#')[0];
      } else {
        newBase = newBase.value;
      }
      if (newBase.slice(-1) !== '/') {
        $rdf.log.error(appPathSegment + ': No / at end of uriPrefix ' + newBase); // @@ paramater?
        newBase = newBase + '/';
      }
      var now = new Date();
      newBase += appPathSegment + '/id' + now.getTime() + '/'; // unique id

      initializeNewInstanceAtBase(thisInstance, newBase);
    };
    var initializeNewInstanceAtBase = function initializeNewInstanceAtBase(thisInstance, newBase) {
      var options = {
        thisInstance: thisInstance,
        newBase: newBase
      };
      this.mintNew(context, options).then(function (options) {
        var p = div.appendChild(dom.createElement('p'));
        p.setAttribute('style', 'font-size: 140%;');
        p.innerHTML = "Your <a href='" + options.newInstance.uri + "'><b>new scheduler</b></a> is ready to be set up. " + "<br/><br/><a href='" + options.newInstance.uri + "'>Say when you what days work for you.</a>";
      })["catch"](function (error) {
        complainIfBad(false, 'Error createing new scheduler at ' + options.newInstance + ': ' + error);
      });
    };

    // ///////////////////////

    var getForms = function getForms() {
      console.log('getforms()');
      getDetails();
      /*
      fetcher.nowOrWhenFetched(formsURI, undefined, function (ok, body) {
        console.log('getforms() ok? ' + ok)
        if (!ok) return complainIfBad(ok, body)
        getDetails()
      })
      */
    };
    var getDetails = function getDetails() {
      console.log('getDetails()'); // Looking for blank screen hang-up
      fetcher.nowOrWhenFetched(detailsDoc.uri, undefined, function (ok, body) {
        console.log('getDetails() ok? ' + ok);
        if (!ok) return complainIfBad(ok, body);
        showAppropriateDisplay();
      });
    };
    var showAppropriateDisplay = function showAppropriateDisplay() {
      console.log('showAppropriateDisplay()');
      _solidLogic.authn.checkUser().then(function (webId) {
        if (!webId) {
          return showSignon();
        }

        // On gh-pages, the turtle will not load properly (bad mime type)
        // but we can trap it as being a non-editable server.

        if (!kb.updater.editable(detailsDoc.uri, kb) || kb.holds(subject, ns.rdf('type'), ns.wf('TemplateInstance'))) {
          // This is read-only example e.g. on github pages, etc
          showBootstrap(div);
          return;
        }
        var ready = kb.any(subject, ns.sched('ready'));
        if (!ready) {
          showForms();
        } else {
          // no editing not author
          getResults();
        }
      });
    };
    var showSignon = function showSignon() {
      clearElement(naviMain);
      var signonContext = {
        div: div,
        dom: dom
      };
      UI.login.ensureLoggedIn(signonContext).then(function (context) {
        me = context.me;
        waitingForLogin = false; // untested
        showAppropriateDisplay();
      });
    };
    var showBootstrap = function showBootstrap() {
      var div = clearElement(naviMain);
      div.appendChild(UI.login.newAppInstance(dom, {
        noun: 'poll'
      }, initializeNewInstanceInWorkspace));
      div.appendChild(dom.createElement('hr')); // @@

      var p = div.appendChild(dom.createElement('p'));
      p.textContent = 'Where would you like to store the data for the poll?  ' + 'Give the URL of the directory where you would like the data stored.';
      var baseField = div.appendChild(dom.createElement('input'));
      baseField.setAttribute('type', 'text');
      baseField.size = 80; // really a string
      baseField.label = 'base URL';
      baseField.autocomplete = 'on';
      div.appendChild(dom.createElement('br')); // @@

      var button = div.appendChild(dom.createElement('button'));
      button.setAttribute('style', inputStyle);
      button.textContent = 'Start new poll at this URI';
      button.addEventListener('click', function (_e) {
        var newBase = baseField.value;
        if (newBase.slice(-1) !== '/') {
          newBase += '/';
        }
        initializeNewInstanceAtBase(thisInstance, newBase);
      });
    };

    // ///////////// The forms to configure the poll

    var doneButton = dom.createElement('button');
    var showForms = function showForms() {
      clearElement(naviCenter); // Remove refresh button if nec
      var div = naviMain;
      var wizard = true;
      var currentSlide = 0;
      var gotDoneButton = false;
      if (wizard) {
        var forms = [form1, form2, form3];
        var slides = [];
        currentSlide = 0;
        for (var f = 0; f < forms.length; f++) {
          var slide = dom.createElement('div');
          UI.widgets.appendForm(document, slide, {}, subject, forms[f], detailsDoc, complainIfBad);
          slides.push(slide);
        }
        var refresh = function refresh() {
          clearElement(naviMain).appendChild(slides[currentSlide]);
          if (currentSlide === 0) {
            b1.setAttribute('disabled', '');
          } else {
            b1.removeAttribute('disabled');
          }
          if (currentSlide === slides.length - 1) {
            b2.setAttribute('disabled', '');
            if (!gotDoneButton) {
              // Only expose at last slide seen
              naviCenter.appendChild(emailButton); // could also check data shape
              naviCenter.appendChild(doneButton); // could also check data shape
              gotDoneButton = true;
            }
          } else {
            b2.removeAttribute('disabled');
          }
        };
        var b1 = clearElement(naviLeft).appendChild(dom.createElement('button'));
        b1.setAttribute('style', inputStyle);
        b1.textContent = '<- go back';
        b1.addEventListener('click', function (_e) {
          if (currentSlide > 0) {
            currentSlide -= 1;
            refresh();
          }
        }, false);
        var b2 = clearElement(naviRight).appendChild(dom.createElement('button'));
        b2.setAttribute('style', inputStyle);
        b2.textContent = 'continue ->';
        b2.addEventListener('click', function (_e) {
          if (currentSlide < slides.length - 1) {
            currentSlide += 1;
            refresh();
          }
        }, false);
        refresh();
      } else {
        // not wizard one big form
        // @@@ create the initial config doc if not exist
        var table = div.appendChild(dom.createElement('table'));
        UI.widgets.appendForm(document, table, {}, subject, form1, detailsDoc, complainIfBad);
        UI.widgets.appendForm(document, table, {}, subject, form2, detailsDoc, complainIfBad);
        UI.widgets.appendForm(document, table, {}, subject, form3, detailsDoc, complainIfBad);
        naviCenter.appendChild(doneButton); // could also check data shape
      }
      // @@@  link config to results

      var insertables = [];
      insertables.push($rdf.st(subject, ns.sched('availabilityOptions'), ns.sched('YesNoMaybe'), detailsDoc));
      insertables.push($rdf.st(subject, ns.sched('ready'), new Date(), detailsDoc));
      insertables.push($rdf.st(subject, ns.sched('results'), resultsDoc, detailsDoc)); // @@ also link in results

      doneButton.setAttribute('style', inputStyle);
      doneButton.textContent = 'Go to poll';
      doneButton.addEventListener('click', function (_e) {
        if (kb.any(subject, ns.sched('ready'))) {
          // already done
          getResults();
          naviRight.appendChild(emailButton);
        } else {
          naviRight.appendChild(emailButton);
          kb.updater.update([], insertables, function (uri, success, errorBody) {
            if (!success) {
              complainIfBad(success, errorBody);
            } else {
              // naviRight.appendChild(emailButton)
              getResults();
            }
          });
        }
      }, false);
      var emailButton = dom.createElement('button');
      emailButton.setAttribute('style', inputStyle);
      var emailIcon = emailButton.appendChild(dom.createElement('img'));
      emailIcon.setAttribute('src', UI.icons.iconBase + 'noun_480183.svg'); // noun_480183.svg
      emailIcon.setAttribute('style', buttonIconStyle);
      // emailButton.textContent = 'email invitations'
      emailButton.addEventListener('click', function (_e) {
        var title = kb.anyValue(subject, ns.cal('summary')) || kb.anyValue(subject, ns.dc('title')) || '';
        var mailto = 'mailto:' + kb.each(subject, ns.sched('invitee')).map(function (who) {
          var mbox = kb.any(who, ns.foaf('mbox'));
          return mbox ? mbox.uri.replace('mailto:', '') : '';
        }).join(',') + '?subject=' + encodeURIComponent(title + '-- When can we meet?') + '&body=' + encodeURIComponent(title + '\n\nWhen can you?\n\nSee ' + subject + '\n');
        // @@ assumed there is a data browser

        console.log('Mail: ' + mailto);
        window.location.href = mailto;
      }, false);
    }; // showForms

    // Ask for each day, what times .. @@ to be added some time
    /*
    const setTimesOfDay = function () {
      const i, j, x, y, slot, cell, day
      const insertables = []
      const possibleDays = kb.each(invitation, ns.sched('option'))
        .map(function (opt) {return kb.any(opt, ns.cal('dtstart'))})
      const cellLookup = []
      const slots = kb.each(invitation, ns.sched('slot'))
      if (slots.length === 0) {
        for (i = 0; i < 2; i++) {
          slot = UI.widgets.newThing(detailsDoc)
          insertables.push($rdf.st(invitation, ns.sched('slot'), slot))
          insertables.push($rdf.st(slot, ns.rdfs('label'), 'slot ' + (i + 1)))
          for (j = 0; j < possibleDays.length; j++) {
            day - possibleDays[j]
            x = kb.any(slot, ns.rdfs('label'))
            y = kb.any(day, ns.cal('dtstart'))
            cell = UI.widgets.newThing(detailsDoc)
            cellLookup[x.toNT() + y.toNT()] = cell
            insertables.push($rdf.st(slot, ns.sched('cell'), cell))
            insertables.push($rdf.st(cell, ns.sched('day'), possibleDays[j]))
          }
        }
      }
       const query = new $rdf.Query('TimesOfDay')
      const v = {}['day', 'label', 'value', 'slot', 'cell'].map(function (x) {
        query.consts.push(v[x] = $rdf.constiable(x)) })
      query.pat.add(invitation, ns.sched('slot'), v.slot)
      query.pat.add(v.slot, ns.rdfs('label'), v.label)
      query.pat.add(v.slot, ns.sched('cell'), v.cell)
      query.pat.add(v.cell, ns.sched('timeOfDay'), v.value)
      query.pat.add(v.cell, ns.sched('day'), v.day)
       const options = {}
      options.set_x = kb.each(subject, ns.sched('slot')) // @@@@@ option -> dtstart in future
      options.set_x = options.set_x.map(function (opt) { return kb.any(opt, ns.rdfs('label')) })
       options.set_y = kb.each(subject, ns.sched('option')); // @@@@@ option -> dtstart in future
      options.set_y = options.set_y.map(function (opt) { return kb.any(opt, ns.cal('dtstart')) })
       const possibleTimes = kb.each(invitation, ns.sched('option'))
        .map(function (opt) { return kb.any(opt, ns.cal('dtstart')) })
       const displayTheMatrix = function () {
        const matrix = div.appendChild(UI.matrix.matrixForQuery(
          dom, query, v.time, v.author, v.value, options, function () {}))
         matrix.setAttribute('class', 'matrix')
         const refreshButton = dom.createElement('button')
        refreshButton.setAttribute('style', inputStyle)
        refreshButton.textContent = 'refresh'
        refreshButton.addEventListener('click', function (e) {
          refreshButton.disabled = true
          store.fetcher.nowOrWhenFetched(subject.doc(), undefined, function (ok, body) {
            if (!ok) {
              console.log('Cant refresh matrix' + body)
            } else {
              matrix.refresh()
              refreshButton.disabled = false
            }
          })
        }, false)
         clearElement(naviCenter)
        naviCenter.appendChild(refreshButton)
      }
       const dataPointForNT = []
       const doc = resultsDoc
      options.set_y = options.set_y.filter(function (z) { return (! z.sameTerm(me)) })
      options.set_y.push(me) // Put me on the end
       options.cellFunction = function (cell, x, y, value) {
        // const point = cellLookup[x.toNT() + y.toNT()]
         if (y.sameTerm(me)) {
          const callbackFunction = function () { refreshCellColor(cell, value); }; //  @@ may need that
          const selectOptions = {}
          const predicate = ns.sched('timeOfDay')
          const cellSubject = dataPointForNT[x.toNT()]
          const selector = UI.widgets.makeSelectForOptions(dom, kb, cellSubject, predicate,
            possibleAvailabilities, selectOptions, resultsDoc, callbackFunction)
          cell.appendChild(selector)
        } else if (value !== null) {
          cell.textContent = UI.utils.label(value)
        }
       }
       const responses = kb.each(invitation, ns.sched('response'))
      const myResponse = null
      responses.map(function (r) {
        if (kb.holds(r, ns.dc('author'), me)) {
          myResponse = r
        }
      })
       const id = UI.widgets.newThing(doc).uri
      if (myResponse === null) {
        myResponse = $rdf.sym(id + '_response')
        insertables.push($rdf.st(invitation, ns.sched('response'), myResponse, doc))
        insertables.push($rdf.st(myResponse, ns.dc('author'), me, doc))
      } else {
        const dps = kb.each(myResponse, ns.sched('cell'))
        dps.map(function (dataPoint) {
          const time = kb.any(dataPoint, ns.cal('dtstart'))
          dataPointForNT[time.toNT()] = dataPoint
        })
      }
      for (let j = 0; j < possibleTimes.length; j++) {
        if (dataPointForNT[possibleTimes[j].toNT()]) continue
        const dataPoint = $rdf.sym(id + '_' + j)
        insertables.push($rdf.st(myResponse, ns.sched('cell'), dataPoint, doc))
        insertables.push($rdf.st(dataPoint, ns.cal('dtstart'), possibleTimes[j], doc)) // @@
        dataPointForNT[possibleTimes[j].toNT()] = dataPoint
      }
      if (insertables.length) {
        store.updater.update([], insertables, function (uri, success, errorBody) {
          if (!success) {
            complainIfBad(success, errorBody)
          } else {
            displayTheMatrix()
          }
        })
      } else { // no insertables
        displayTheMatrix()
      }
    }
    */
    // end setTimesOfDay

    // Read or create empty results file
    function getResults() {
      fetcher.nowOrWhenFetched(resultsDoc.uri, function (ok, body, response) {
        if (!ok) {
          if (response.status === 404) {
            // /  Check explicitly for 404 error
            console.log('Initializing details file ' + resultsDoc);
            updater.put(resultsDoc, [], 'text/turtle', function (uri2, ok, message) {
              if (ok) {
                clearElement(naviMain);
                showResults();
              } else {
                complainIfBad(ok, 'FAILED to create results file at: ' + resultsDoc.uri + ' : ' + message);
                console.log('FAILED to craete results file at: ' + resultsDoc.uri + ' : ' + message);
              }
            });
          } else {
            // Other error, not 404 -- do not try to overwite the file
            complainIfBad(ok, 'FAILED to read results file: ' + body);
          }
        } else {
          // Happy read
          clearElement(naviMain);
          showResults();
        }
      });
    }
    function showResults() {
      //       Now the form for responsing to the poll
      //

      // div.appendChild(dom.createElement('hr'))

      // const invitation = subject
      var title = kb.any(invitation, ns.cal('summary'));
      var comment = kb.any(invitation, ns.cal('comment'));
      var location = kb.any(invitation, ns.cal('location'));
      var div = naviMain;
      if (title) div.appendChild(dom.createElement('h3')).textContent = title;
      if (location) {
        div.appendChild(dom.createElement('address')).textContent = location.value;
      }
      if (comment) {
        div.appendChild(dom.createElement('p')).textContent = comment.value;
      }
      var author = kb.any(invitation, ns.dc('author'));
      if (author) {
        var authorName = kb.any(author, ns.foaf('name'));
        if (authorName) {
          div.appendChild(dom.createElement('p')).textContent = authorName;
        }
      }
      var query = new $rdf.Query('Responses');
      var v = {};
      var vs = ['time', 'author', 'value', 'resp', 'cell'];
      vs.forEach(function (x) {
        query.vars.push(v[x] = $rdf.variable(x));
      });
      query.pat.add(invitation, ns.sched('response'), v.resp);
      query.pat.add(v.resp, ns.dc('author'), v.author);
      query.pat.add(v.resp, ns.sched('cell'), v.cell);
      query.pat.add(v.cell, ns.sched('availabilty'), v.value);
      query.pat.add(v.cell, ns.cal('dtstart'), v.time);

      // Sort by by person @@@

      var options = {};
      options.set_x = kb.each(subject, ns.sched('option')); // @@@@@ option -> dtstart in future
      options.set_x = options.set_x.map(function (opt) {
        return kb.any(opt, ns.cal('dtstart'));
      });
      options.set_y = kb.each(subject, ns.sched('response'));
      options.set_y = options.set_y.map(function (resp) {
        return kb.any(resp, ns.dc('author'));
      });
      var possibleTimes = kb.each(invitation, ns.sched('option')).map(function (opt) {
        return kb.any(opt, ns.cal('dtstart'));
      });
      var displayTheMatrix = function displayTheMatrix() {
        var matrix = div.appendChild(UI.matrix.matrixForQuery(dom, query, v.time, v.author, v.value, options, function () {}));
        matrix.setAttribute('class', 'matrix');
        var refreshButton = dom.createElement('button');
        refreshButton.setAttribute('style', inputStyle);
        // refreshButton.textContent = 'refresh' // noun_479395.svg
        var refreshIcon = dom.createElement('img');
        refreshIcon.setAttribute('src', UI.icons.iconBase + 'noun_479395.svg');
        refreshIcon.setAttribute('style', buttonIconStyle);
        refreshButton.appendChild(refreshIcon);
        refreshButton.addEventListener('click', function (_e) {
          refreshButton.disabled = true;
          kb.fetcher.refresh(resultsDoc, function (ok, body) {
            if (!ok) {
              console.log('Cant refresh matrix' + body);
            } else {
              matrix.refresh();
              refreshButton.disabled = false;
            }
          });
        }, false);
        clearElement(naviCenter);
        naviCenter.appendChild(refreshButton);
      };

      // @@ Give other combos too-- see schedule ontology
      // const possibleAvailabilities = [ SCHED('No'), SCHED('Maybe'), SCHED('Yes') ]

      // const me = authn.currentUser()

      var dataPointForNT = [];
      var loginContext = {
        div: naviCenter,
        dom: dom
      };
      UI.login.ensureLoggedIn(loginContext).then(function (context) {
        var me = context.me;
        var doc = resultsDoc;
        options.set_y = options.set_y.filter(function (z) {
          return !z.sameTerm(me);
        });
        options.set_y.push(me); // Put me on the end

        options.cellFunction = function (cell, x, y, value) {
          if (value !== null) {
            kb.fetcher.nowOrWhenFetched(value.uri.split('#')[0], undefined, function (ok, _error) {
              if (ok) refreshCellColor(cell, value);
            });
          }
          if (y.sameTerm(me)) {
            var callbackFunction = function callbackFunction() {
              refreshCellColor(cell, value);
            }; //  @@ may need that
            var selectOptions = {};
            var predicate = ns.sched('availabilty');
            var cellSubject = dataPointForNT[x.toNT()];
            var selector = UI.widgets.makeSelectForOptions(dom, kb, cellSubject, predicate, possibleAvailabilities, selectOptions, resultsDoc, callbackFunction);
            cell.appendChild(selector);
          } else if (value !== null) {
            cell.textContent = UI.utils.label(value);
          }
        };
        var responses = kb.each(invitation, ns.sched('response'));
        var myResponse = null;
        responses.forEach(function (r) {
          if (kb.holds(r, ns.dc('author'), me)) {
            myResponse = r;
          }
        });
        var insertables = []; // list of statements to be stored

        var id = UI.widgets.newThing(doc).uri;
        if (myResponse === null) {
          myResponse = $rdf.sym(id + '_response');
          insertables.push($rdf.st(invitation, ns.sched('response'), myResponse, doc));
          insertables.push($rdf.st(myResponse, ns.dc('author'), me, doc));
        } else {
          var dps = kb.each(myResponse, ns.sched('cell'));
          dps.forEach(function (dataPoint) {
            var time = kb.any(dataPoint, ns.cal('dtstart'));
            dataPointForNT[time.toNT()] = dataPoint;
          });
        }
        for (var j = 0; j < possibleTimes.length; j++) {
          if (dataPointForNT[possibleTimes[j].toNT()]) continue;
          var dataPoint = $rdf.sym(id + '_' + j);
          insertables.push($rdf.st(myResponse, ns.sched('cell'), dataPoint, doc));
          insertables.push($rdf.st(dataPoint, ns.cal('dtstart'), possibleTimes[j], doc)); // @@
          dataPointForNT[possibleTimes[j].toNT()] = dataPoint;
        }
        if (insertables.length) {
          kb.updater.update([], insertables, function (uri, success, errorBody) {
            if (!success) {
              complainIfBad(success, errorBody);
            } else {
              displayTheMatrix();
            }
          });
        } else {
          // no insertables
          displayTheMatrix();
        }
      }); // @@@@ end of .then

      // If I made this in the first place, allow me to edit it.
      // @@ optionally -- allows others to if according to original
      var instanceCreator = kb.any(subject, ns.foaf('maker')); // owner?
      if (!instanceCreator || instanceCreator.sameTerm(me)) {
        var editButton = dom.createElement('button');
        editButton.setAttribute('style', inputStyle);
        // editButton.textContent = '(Modify the poll)' // noun_344563.svg
        var editIcon = dom.createElement('img');
        editIcon.setAttribute('src', UI.icons.iconBase + 'noun_344563.svg');
        editIcon.setAttribute('style', buttonIconStyle);
        editButton.appendChild(editIcon);
        editButton.addEventListener('click', function (_e) {
          clearElement(div);
          showForms();
        }, false);
        clearElement(naviLeft);
        naviLeft.appendChild(editButton);
      }

      // div.appendChild(editButton)

      clearElement(naviRight);
      naviRight.appendChild(newInstanceButton());
    } // showResults

    var div = dom.createElement('div');
    var structure = div.appendChild(dom.createElement('table')); // @@ make responsive style
    structure.setAttribute('style', 'background-color: white; min-width: 40em; min-height: 13em;');
    var naviLoginoutTR = structure.appendChild(dom.createElement('tr'));
    naviLoginoutTR.appendChild(dom.createElement('td'));
    naviLoginoutTR.appendChild(dom.createElement('td'));
    naviLoginoutTR.appendChild(dom.createElement('td'));
    var logInOutButton = null;
    /*
    const logInOutButton = UI.login.loginStatusBox(dom, setUser)
    // floating divs lead to a mess
    // logInOutButton.setAttribute('style', 'float: right') // float the beginning of the end
    naviLoginout3.appendChild(logInOutButton)
    logInOutButton.setAttribute('style', 'margin-right: 0em;')
    */

    var naviTop = structure.appendChild(dom.createElement('tr'));
    var naviMain = naviTop.appendChild(dom.createElement('td'));
    naviMain.setAttribute('colspan', '3');
    var naviMenu = structure.appendChild(dom.createElement('tr'));
    naviMenu.setAttribute('class', 'naviMenu');
    naviMenu.setAttribute('style', ' text-align: middle; vertical-align: middle; padding-top: 4em; ');
    //    naviMenu.setAttribute('style', 'margin-top: 3em;')
    var naviLeft = naviMenu.appendChild(dom.createElement('td'));
    var naviCenter = naviMenu.appendChild(dom.createElement('td'));
    var naviRight = naviMenu.appendChild(dom.createElement('td'));
    getForms();
    return div;
  } // render
}; // property list
// ends
//# sourceMappingURL=schedulePane.js.map