/*************************************************************
 *
 *  latest.js
 *  
 *  Replacement for cdn.mathjax.org/mathjax/latest that loads the
 *  latest (2.x) version of MathJax from cdnjs, rawgit.com, or jsdelivr
 *  depending on where it was loaded from.
 *  
 *  ---------------------------------------------------------------------
 *  
 *  Copyright (c) 2017 The MathJax Consortium
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

(function () {

   var CDN = {
     'cdnjs.cloudflare.com': {
       api: 'https://api.cdnjs.com/libraries/mathjax?fields=version',
       version: 'version',
       mathjax: 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/'
     },
     
     'cdn.rawgit.com': {
       api: 'https://api.github.com/repos/mathjax/mathjax/releases/latest',
       version: 'tag_name',
       mathjax: 'https://cdn.rawgit.com/mathjax/MathJax/'
     },
     
     'cdn.jsdelivr.net': {
       api: 'https://api.jsdelivr.com/v1/jsdelivr/libraries?name=mathjax&lastversion=*',
       version: 'lastversion',
       mathjax: 'https://cdn.jsdelivr.net/mathjax/'
     }
   };
   
   function Error(message) {
     if (console && console.log) console.log(message);
   }
   
   function getScript() {
     if (document.currentScript) return document.currentScript;
     var scripts = document.getElementsByTagName("script");
     for (var i = 0, m = scripts.length; i < m; i++) {
       var script = scripts[i];
       for (var cdn in CDN) {if (CDN.hasOwnProperty(cdn)) {
         var url = CDN[cdn].mathjax;
         if (script.src && script.src.substr(0,url.length) === url) return script;
       }}
     }
   }
   
   function getCDN(script) {
     if (!script) return;
     var cdn = script.src.replace(/https:\/\//,'').replace(/[\/\?].*/,'');
     return CDN[cdn];
   }
   
   var cookiePattern = /(?:^|;\s*)mjx\.latest=([^;]*)(?:;|$)/;
   function getVersion() {
     var match;
     try {match = cookiePattern.exec(document.cookie)} catch (err) {}
     if (match && match[1] !== '') return match[1];
   }
   function setVersion(version) {
     cookie = 'mjx.latest=' + version;
     var time = new Date();
     time.setDate(time.getDate() + 7);
     cookie += '; expires=' + time.toGMTString();
     cookie += '; path=/';
     try {document.cookie = cookie} catch (err) {}
   }
   
   function getXMLHttpRequest() {
     if (window.XMLHttpRequest) return new XMLHttpRequest();
     if (window.ActiveXObject) {
       try {return new ActiveXObject("Msxml2.XMLHTTP")} catch (err) {}
       try {return new ActiveXObject("Microsoft.XMLHTTP")} catch (err) {}
     }
   }
   
   function loadMathJax(url) {
     var script = document.createElement('script');
     script.type = 'text/javascript';
     script.async = true;
     script.src = url;
     var head = document.head || document.getElementsByTagName('head')[0] || document.body;
     if (head) {
       head.appendChild(script);
     } else {
       Error("Can't find the document <head> element");
     }
   }
   
   function loadDefaultMathJax() {
     var script = getScript();
     if (script) {
       loadMathJax(script.src.replace(/\/latest\.js/, "/MathJax.js"));
     } else {
       Error("Can't determine the URL for loading MathJax");
     }
   }
   
   function getLatestMathJax(cdn,config,unpacked) {
     var request = getXMLHttpRequest();
     if (request) {
       request.onreadystatechange = function() {
         if (request.readyState === 4) {
           if (request.status === 200) {
             var json = JSON.parse(request.responseText);
             if (json instanceof Array) json = json[0];
             var version = json[cdn.version];
             if (version.substr(0,2) === '2.') {
               setVersion(version);
               loadMathJax(cdn.mathjax + json[cdn.version] + unpacked + '/MathJax.js' + config);
               return;
             }
           } else {
             Error("Problem aquiring MathJax version: status = " + request.status);
           }
           loadDefaultMathJax();
         }
       }
       request.open('GET', cdn.api, true); 
       request.send(null);
     } else {
       Error("Can't create XMLHttpRequest object");
       loadDefaultMathJax();
     }
   }
   
   var script = getScript();
   var cdn = getCDN(script);
   if (cdn) {
     var config = script.src.replace(/.*?(\?|$)/, "$1");
     config += (config ? '&' : '?') + 'latest';
     var unpacked = (script.src.match(/\/unpacked\/latest\.js/) ? "/unpacked" : "");
     var version = getVersion();
     if (version) {
       loadMathJax(cdn.mathjax + version + unpacked + '/MathJax.js' + config);
     } else {
       getLatestMathJax(cdn, config, unpacked);
     }
   } else {
     loadDefaultMathJax();
   }

})();
