<?php if (!defined('PmWiki')) exit();
/**
  Pending Changes extension for PmWiki
  Periodically fetches the current page revision number
  and adds a message to the page and to the document.title.
  Written by (c) Petko Yotov 2019-2020 www.pmwiki.org/petko

  This text is written for PmWiki; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published
  by the Free Software Foundation; either version 3 of the License, or
  (at your option) any later version. See pmwiki.php for full details
  and lack of warranty.
*/
# Version date
$RecipeInfo['PendingChanges']['Version'] = '20201220';

SDVA($HandleActions, array('pending'=> 'HandlePendingChanges'));
SDVA($HandleAuth, array('pending' => 'read'));
SDVA($HTMLStylesFmt, array('PendingChanges'=>'#pendingchanges {background-color: #ff8; cursor: pointer;}'));
XLSDV('en',array(
  'PendingChanges' => '(%s) Pending changes, click to reload.',
  'EnableDesktopNotifications' => 'Enable desktop notifications',
));

Markup('PendingChanges', '>include', '/\\(:pendingchanges( .+?)?:\\)/', 'FmtPendingChanges');

SDVA($PendingChanges, array(
  'delayminutes' => 5,
  'querySelector' => '#wikitext',
  'where' => 'afterbegin',
  'page-override' => array('Site.AllRecentChangesShort' => 'Site.AllRecentChanges'),
  'script' => '
<script>
var PendingChangesVars = %s;
PendingChangesVars.prev = PendingChangesVars.rev;
function zpad(n) {
  if(n<10) return "0" +n;
  return n;
}

function CheckPendingChanges() {
  var xhr;
  if (window.XMLHttpRequest) xhr = new XMLHttpRequest();
  else if (window.ActiveXObject) xhr = new ActiveXObject("Microsoft.XMLHTTP");
  else return false;
  var ltreload = document.querySelector("small.ltreload");
  ltreload.innerHTML += "...";

  xhr.open("GET", PendingChangesVars.url, true);
  xhr.send("");

  xhr.onreadystatechange = function() {
    if(xhr.readyState != 4) return;
    var rt = xhr.responseText;
    if(xhr.status != 200 || rt.indexOf("ERROR")>=0 || rt == "") {
      return;
    }
    var rev = parseInt(rt);
    if(isNaN(rev)) return;
    if(ltreload) {
      var now = new Date();
      var h = zpad(now.getHours()), m = zpad(now.getMinutes());
      ltreload.innerHTML = h + ":" + m;
    }
    if(rev == PendingChangesVars.prev) {
      return;
    }

    PendingChangesVars.prev = rev;
    var el = document.querySelector("#pendingchanges var");
    if(!el) {
      PendingChangesVars.parentNode.insertAdjacentHTML(PendingChangesVars.where, 
        "<div id=\'pendingchanges\'>"+PendingChangesVars.text+"</div>"
        );
      el = document.querySelector("#pendingchanges var");
      if(!el) return clearInterval(PendingChanges.interval);
      document.getElementById("pendingchanges").addEventListener("click", function(){self.location.reload(true);});
    }
    var count = rev - PendingChangesVars.rev;
    el.innerHTML = count;
    document.title = "("+count+") " + document.title.replace(/^\\s*\\(\\d+\\)\\s*/,"");
    if (Notification.permission === "granted") 
      var n = new Notification(document.title, {body: document.querySelector("#pendingchanges").textContent});
  };
}


document.addEventListener("DOMContentLoaded", function(){
  var parent = document.querySelector(PendingChangesVars.querySelector);
  if(!parent) return;
  PendingChangesVars.parentNode = parent;
  
  PendingChangesVars.interval = setInterval(CheckPendingChanges, PendingChangesVars.delayminutes*1000*60);
  if(! window.Notification) window.Notification = {permission:"denied"};
  if (Notification.permission === "default") {
    parent.insertAdjacentHTML(PendingChangesVars.where, 
      " <button id=\'pc_notif\'>"+PendingChangesVars.enable+"</button>");
    document.getElementById("pc_notif").addEventListener("click", function(){
      Notification.requestPermission();
      this.parentNode.removeChild(this);
    });
  
  }
});


</script>
',
));

function FmtPendingChanges($m) {
  global $HTMLHeaderFmt, $PendingChanges, $PCache;
  extract($GLOBALS['MarkupToHTML']);
  
  
  $pn = IsEnabled($PendingChanges['page-override'][$pagename], $pagename);
  if(! isset($PCache[$pn]['rev'])) {
    $page = RetrieveAuthPage($pn, 'read', false, READPAGE_CURRENT);
    PCache($pn, $page);
  }
  
  $out = array(
    'rev' => $PCache[$pn]['rev'],
    'text' => sprintf(XL('PendingChanges'), '<var></var>'),
    'enable' => XL('EnableDesktopNotifications'),
    'delayminutes' => $PendingChanges['delayminutes'],
    'querySelector' => $PendingChanges['querySelector'],
    'where' => $PendingChanges['where'],
    'url' => FmtPageName('{$PageUrl}?action=pending', $pagename)
  );
  $script = sprintf($PendingChanges['script'], json_encode($out));
  SDVA($HTMLHeaderFmt, array('PendingChanges'=>$script));
  return '';
}

function HandlePendingChanges($pagename, $auth='read') {
  global $PendingChanges;
  
  $pn = IsEnabled($PendingChanges['page-override'][$pagename], $pagename);

  $page = RetrieveAuthPage($pn, $auth, false, READPAGE_CURRENT);
  
  header('Content-Type: text/plain');
  echo intval(@$page['rev']);
  exit;
}