/*
  JavaScript media utilities for PmWiki
  (c) 2009-2026 Petko Yotov www.pmwiki.org/petko
  based on PmWiki addon Ape
  licensed GNU GPLv2 or any more recent version released by the FSF.

  $Id: pmwiki-media.js 5434 2026-05-13 15:47:52Z petko $
*/

(async function(__script__){
  
  const { echo, Q, dce, getConf, on, fire, tap, pd, adj, 
    ready, floatval } = PmLib;
    
  var Config = getConf(__script__);

  const NF = NodeFilter, NTN = Node.TEXT_NODE;
  const nfa = NF.FILTER_ACCEPT, nfr = NF.FILTER_REJECT, nfs = NF.FILTER_SKIP;
  const reject = /^(a|area|button|label|summary|input|textarea|select|datalist|style|script|iframe|object|embed|source|track|time)$/i;
  const stop = /^h[123]|audio|video$/i;
  
  function mkwalker() {
    const walker = document.createTreeWalker(
      document.body,
      NF.SHOW_ELEMENT | NF.SHOW_TEXT,
      {
        acceptNode(node) {
          if(node.nodeType === NTN) 
            return /\b\d+:\d\d\b/.test(node.textContent) ? nfa : nfr;
          const tag = node.tagName
          if(reject.test(tag)) return nfr;
          if(stop.test(tag)) return nfa;
          return nfs;
        }
      }
    );
    return walker;
  }
  
  function walk(walker, startnode, container) {
    let todo = [];
    walker.currentNode = startnode;
    let node = walker.nextNode();
    while (node) {
      if(container && !container.contains(node)) break;
      if(node.tagName?.match(stop)) break;
      if(node.nodeType === NTN) todo.push(node);
      node = walker.nextNode();
    }
    return todo;
  }
  
  function mj1(media) {
    const walker = mkwalker();
    const container = media.closest('#wikitext,table.markup,details');
    let todo = walk(walker, media, container);
    if(media.id) {
      let ccs = Q(`.nav-${media.id}`); // custom nav containers
      for(let c of ccs) todo.push(...walk(walker, c, c));
    }
    for(let node of todo) findtimes(node);
    
    function findtimes(node) {
      let rx = /((?:\d+:)?\d+:\d\d(?:\.\d+)?)/
      let parts = node.textContent.split(rx);
      if(parts.length==1) return;
      let out = [];
      let found = 0;
      for(let part of parts) {
        if(part === '') continue;
        if(part.match(rx)) {
          part = dce.a({cn:'mnav', h:'#', rc:[dce.time({tc:part})]});
          tap(part, clicktime);
        }
        out.push(part);
      }
      adj.rw(node, ...out);
    }
    function clicktime(e) {
      pd.sp(e);
      let parts = this.textContent.split(/:/).reverse().slice(0, 3);
      let sec = 0;
      for(let j=0;j<parts.length;j++)
        sec += Math.pow(60, j)*parseFloat(parts[j]);
      media.currentTime = sec;
      media.play();
    }
  }
  
  function pauseothers(e) {
    let media = Q('audio,video');
    for(let m of media) if(m!==this && !m.paused) m.pause()
  }
  
  function setspeed(e) {
    let speed = floatval(this.dataset.speed);
    if(0.25<=speed&&speed<=10.0) this.playbackRate = speed;
  }
  
  function initmedia() {
    const medias = Q('audio,video');
    for(let m of medias) if(!m.closest('.embed,.mediajump')) mj1(m);
    on.play(medias, pauseothers);
    on.loadedmetadata('audio[data-speed],video[data-speed]', setspeed);
  }
  
  ready.queue(initmedia);
  
})(document.currentScript);
