<?php if (!defined('PmWiki')) exit();
/*  Copyright 2015-2026 Petko Yotov (5ko@5ko.fr)
    This file is part of 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 2 of the License, or
    (at your option) any later version.  See pmwiki.php for full details.

    This script enables embedding of <audio> and <video> bare links.
    Note, this script is in the UTF-8 encoding without BOM.
    Partly based on the Cookbook:Ape recipe, rewritten in PHP.

    Script maintained by Petko YOTOV www.pmwiki.org/petko
*/

SDVA($PmMedia, [
  # For <audio> and <video>, in the preferred order
  'AudioExts' => 'opus|weba|m4a|ogg|mp3|flac|wav',
  'VideoExts' => 'webm|mp4|m4v|ogv|mov',
  'PosterExts' => 'webp|jpg|jpeg|png',
  # For both attached files and remote URLs
  'TagFmt' => '<$MTag $MAttr>$MTracks $[Unsupported media, download] $MLinks.</$MTag>',
  'EnableUploadEmbed' => 1,
  'EnableRemoteEmbed' => 1,
]);
SDV($PmMedia['ExtPattern'], "\\.(?:{$PmMedia['AudioExts']}|{$PmMedia['VideoExts']}|"
  .strtoupper("{$PmMedia['AudioExts']}|{$PmMedia['VideoExts']}").")");
SDVA($PmMedia['DefaultAttrs'], [
  'controls' => true,
  'class' => 'pmmedia',
]);

SDVA($HTMLHeaderFmt, array('pmwiki-media' =>
  "<script type='text/javascript' src='\$FarmPubDirUrl/lib/pmwiki-media.js'></script>"
));

## inline audio, video (bare link)
Markup('media','<urllink',
  "/\\b(?>(\\L))([^\\s$UrlExcludeChars]+{$PmMedia['ExtPattern']})(#\\S+)?/",
  "LinkMedia");

# SDV($imgTag, '(?:img|object|embed|video)');
# SDVA($WikiStyleApply, ['media'=>'audio|video|iframe']);
# SDVA($WikiStyle, ['media'=>['apply'=>'media']]);

function LinkMedia($m) {
  global $PmMedia, $LinkFunctions, $UploadExts, $FmtV, $XLLangs;
  extract($GLOBALS['MarkupToHTML']);
  
  list($link, $imap, $path) = $m;
  $hash = $m[3]??'';
  
  $M = $PmMedia;
  
  if (preg_match("/\\.({$M['AudioExts']})$/i", $path)) {
    $tag = 'audio';
    $exts = $M['AudioExts'];
  }
  else {
    $tag = 'video';
    $exts = $M['VideoExts'];
  }
  $attrs = $M['DefaultAttrs'];
  
  $sourceurls = $links = $tracks = [];
  
  $fragment = '';
  $defaultlang = false;
  if ($hash) {
    $parts = explode(';', substr($m[3], 1));
    foreach($parts as $part) {
      if (preg_match('/^(poster|src)=/i', $part)) continue;
      elseif (preg_match('/^(audio|video)$/', $part)) $tag = $part;
      elseif (preg_match('/^([\d.]*)x(\d*)$/i', $part, $d)) {
        if ($d[1]) {
          $w = floatval($d[1]);
          if (0.25<=$w&&$w<=10) $attrs['data-speed'] = $w;
          elseif ($w>10) $attrs['width'] = intval($w);
        }
        if ($d[2]) $attrs['height'] = $d[2];
      }
      elseif (preg_match('/^t=[\\d.:,]+$/', $part)) $fragment = "#$part";
      elseif (preg_match('/^([a-z][-a-z0-9]*)=0$/i', $part, $n)) unset($attrs[$n[2]]);
      elseif (preg_match('/^lang=(\\S+)$/i', $part, $l)) $defaultlang = $l[1];
      elseif (preg_match('/^(?!on)[a-z][-a-z0-9]*$/i', $part)) $attrs[$part] = true;
      elseif (preg_match('/^(?!on)([a-z][-a-z0-9]*)=(.+)$/i', $part, $p))
        $attrs[$p[1]] = $p[2];
    }
  }
  
  
  $lf = $LinkFunctions[$imap] ?? '';
  $url = '';
  if ($lf == 'LinkUpload') {
    $url = $M['EnableUploadEmbed']? DownloadUrl($pagename, $path): '';
    if (!$url)  return Keep(LinkUpload($pagename,$imap,$path,'',$link), 'L');
  
    $baseurl = preg_replace('!(upname=|/)[^=/]+$!', '$1', $url);
    $fpath = $FmtV['$PathUpload'];
    $udir = preg_replace('!/[^/]+$!', '', $fpath);
    $fname = preg_replace('!^.*/!', '', $fpath);
    $basename = preg_replace('/\\.\\w+$/', '', $fname);
    $related = preg_replace('!^.*/!', '', glob("$udir/$basename.*"));
    
    # poster (cover)
    $pex = explode('|', $M['PosterExts']);
    foreach($pex as $e) {
      if (in_array("$basename.$e", $related)) {
        $pu = $baseurl . rawurlencode("$basename.$e");
        $attrs['poster'] = $pu;
        $tag = 'video';
        break;
      }
    }
    # alternative media formats
    $sourceexts = explode('|', $exts);
    foreach($sourceexts as $e) {
      if ("$basename.$e" == $fname) continue;
      if (in_array("$basename.$e", $related)) {
        $ename = rawurlencode("$basename.$e");
        $sourceurls[] = "$baseurl$ename";
      }
    }
    
    # subtitles, chapters, captions
    $seenkinds = [];
    $vtts = preg_grep('/\\.vtt$/', $related);
    $qbn = preg_quote($basename, '/');
    $langs = $M['Langs'];
    foreach($vtts as $vtt) {
      if (preg_match("/^$qbn
        (?:\\.(?P<lang>\\w{2,3}(?:[-](?i:[a-z]{2}|\\d{3}))?))?
        (?:\\.(?P<kind>chapters|captions|subtitles))?
        \\.vtt$/x", $vtt, $v)) {
        
        $kind = $v['kind']?? 'subtitles';
        $lang_loc = $v['lang'] ?? $XLLangs[0];
        if (!$lang_loc) $lang_loc = $XLLangs[0];
        $lang = preg_replace('/-.*$/', '', $lang_loc);
        $loc = preg_replace('/^[^-]*$/', '', $lang_loc);
        
        $label = $langs[$lang_loc] ?? $langs[$lang] ?? $lang_loc;
        if ($label === @$langs[$lang]) $label .= $loc;
      
        $ename = rawurlencode($vtt);
        $track = [
          'src' => $baseurl.$ename,
          'srclang' => $lang_loc,
          'label' => $label,
          'kind' => $kind,
        ];
        if ($defaultlang === $lang_loc && !isset($seenkinds[$kind])) {
          $seenkinds[$kind] = 1;
          $track['default'] = true;
        }
        $tracks[] = $track;
      }
    }
  }
  elseif ($M['EnableRemoteEmbed']) {
    $url = LinkIMap($pagename,$imap,$path,'','','$LinkUrl');
  }
  if (!$url) return Keep(MakeLink($pagename, $link, $link), 'L');
  
  array_unshift($sourceurls, $url);

  $hattrs = PQAA($attrs, false);
  $htracks = '';
  foreach($tracks as $track) {
    $tattr = PQAA($track, false);
    $htracks .= "<track $tattr>";
  }
  
  $sources = '';
  foreach($sourceurls as $u) {
    $e = strtolower(preg_replace('/^.*\\./', '', $u));
    $t = $UploadExts[$e]??'video/mp4';
    $sources .= "<source src=\"$u$fragment\" type=\"$t\">";
    $links[] = MakeLink($pagename, $u, $e);
  }
  
  $FmtV['$MTag'] = $tag;
  $FmtV['$MAttr'] = $hattrs;
  $FmtV['$MTracks'] = $sources.$htracks;
  $FmtV['$MLinks'] = implode(", ", $links);
  
  return Keep(FmtPageName($M['TagFmt'], $pagename), 'L');
}

SDVA($PmMedia['Langs'], [
  # Global Giants (100M+ Speakers)
  'en' => 'English',
  'zh' => '中文',
  'hi' => 'हिन्दी',
  'es' => 'Español',
  'fr' => 'Français',
  'ar' => 'العربية',
  'bn' => 'বাংলা',
  'pt' => 'Português',
  'ru' => 'Русский',
  'ja' => '日本語',
  'pa' => 'ਪੰਜਾਬੀ',
  'id' => 'Bahasa Indonesia',
  'de' => 'Deutsch',
  'ur' => 'اردو',
  
  # Major World Languages (50M+ Speakers)
  'vi' => 'Tiếng Việt',
  'tr' => 'Türkçe',
  'mr' => 'मराठी',
  'te' => 'తెలుగు',
  'ta' => 'தமிழ்',
  'ko' => '한국어',
  'ha' => 'Hausa',
  'sw' => 'Kiswahili',
  'jv' => 'Basa Jawa',
  'it' => 'Italiano',
  'gu' => 'ગુજરાતી',
  'kn' => 'ಕನ್ನಡ',
  'fa' => 'فارسی',
  'th' => 'ไทย',
  'am' => 'አማርኛ',
  'yo' => 'Yorùbá',
  'om' => 'Oromoo',
  
  # Other
  'az' => 'Azərbaycanca',
  'be' => 'Беларуская',
  'bg' => 'Български',
  'bs' => 'Bosanski',
  'ca' => 'Català',
  'cnr'=> 'Crnogorski',
  'cs' => 'Čeština',
  'cy' => 'Cymraeg',
  'da' => 'Dansk',
  'el' => 'Ελληνικά',
  'et' => 'Eesti',
  'eu' => 'Euskara',
  'fi' => 'Suomi',
  'fo' => 'Føroyskt',
  'ga' => 'Gaeilge',
  'gd' => 'Gàidhlig',
  'gl' => 'Galego',
  'he' => 'עברית',
  'hr' => 'Hrvatski',
  'hu' => 'Magyar',
  'hy' => 'Հայերեն',
  'is' => 'Íslenska',
  'ka' => 'ქართული',
  'lt' => 'Lietuvių',
  'lv' => 'Latviešu',
  'mi' => 'Te Reo Māori',
  'mk' => 'Македонски',
  'mt' => 'Malti',
  'nl' => 'Nederlands',
  'no' => 'Norsk',
  'pl' => 'Polski',
  'rm' => 'Rumantsch',
  'ro' => 'Română',
  'sk' => 'Slovenčina',
  'sl' => 'Slovenščina',
  'sq' => 'Shqip',
  'sr' => 'Српски',
  'sv' => 'Svenska',
  'uk' => 'Українська',
]);
