//- Mixins and associated functions

mixin includeShared(filePath, region)
  - var newPath = translatePath(filePath, region);
  !=partial(newPath)

mixin makeExample(_filePath, region, _title, stylePatterns)
  - var filePath = adjustExamplePath ? adjustExamplePath(_filePath) : _filePath;
  - var title = adjustExampleTitle ? adjustExampleTitle(_title) : _title;
  - var language = attributes.language || getExtn(filePath);
  - var frag = getFrag(filePath, region);
  - var defaultFormat = frag.split('\n').length > 2 ? "linenums" : "";
  - var format = attributes.format || defaultFormat;
  - var avoid = !!attributes.avoid;

  if (title)
    if (avoid)
      .example-title.avoid AVOID: #{title}
    else
      .example-title #{title}
  code-example(language="#{language}" format="#{format}")
    != styleString(frag, stylePatterns)

mixin makeTabs(filePaths, regions, tabNames, stylePatterns)
  - filePaths = strSplit(filePaths);
  - regions = strSplit(regions, filePaths.length);
  - tabNames = strSplit(tabNames, filePaths.length);

  code-tabs
      each filePath,index in filePaths
        - var region = regions[index].trim();
        - var tabName = tabNames[index].trim();
        - var language = attributes.language || getExtn(filePath);
        - var format = attributes.format || "linenums";

        - var frag = getFrag(filePath, region);
        - var sps = Array.isArray(stylePatterns) ? stylePatterns[index] : stylePatterns;
        code-pane(language="#{language}" name="#{tabName}" format="#{format}")
            != styleString(frag, sps)

mixin makeJson( filePath, jsonConfig, title, stylePatterns)
  - var language = attributes.language || getExtn(filePath);
  - var format = attributes.format || "linenums";
  - var frag = getFrag(filePath, '');
  - var json = unescapeHtml(frag);
  - var jsonExtract = extractJson(json, jsonConfig);
  - var avoid = !!attributes.avoid;

  if (title)
    if (avoid)
      .example-title.avoid #{title}
    else
      .example-title #{title}
  code-example(language="#{language}" format="#{format}")
    if (jsonExtract == 'ERROR')
      err 错误: 无法通过配置"#{jsonConfig.toString()}"解析JSON
    else
      != styleString(jsonExtract, stylePatterns)

- // Open (and close) an explanation <div>. See QuickStart
script.
  function why(id, backTo) {
    var id = "#"+id;
    var el = document.querySelector(id);
    el.hidden=el.hidden=!el.hidden;

    if (el.hidden && backTo){
      // the next line is required to work around a bug in WebKit (Chrome / Safari)
      location.href = "#";
      location.href =  "#" + backTo;
    }
  }
script.
  function verbose(isVerbose) {
    isVerbose = !! isVerbose;
    var el = document.querySelector('button.verbose.off');
    el.style.display = isVerbose ? 'block' : 'none';
    var el = document.querySelector('button.verbose.on');
    el.style.display = isVerbose ? 'none' : 'block';
    
    CCSStylesheetRuleStyle('main','.l-verbose-section', 'display',
      isVerbose ? 'block' : 'none');
  }

script.
  function CCSStylesheetRuleStyle(stylesheet, selectorText, style, value){
    /* returns the value of the element style of the rule in the stylesheet
    *  If no value is given, reads the value
    *  If value is given, the value is changed and returned
    *  If '' (empty string) is given, erases the value.
    *  The browser will apply the default one
    *
    * string stylesheet: part of the .css name to be recognized, e.g. 'default'
    * string selectorText: css selector, e.g. '#myId', '.myClass', 'thead td'
    * string style: camelCase element style, e.g. 'fontSize'
    * string value optional : the new value
    */
    var CCSstyle = undefined, rules, sheet;
    for(var m in document.styleSheets){
      sheet = document.styleSheets[m];
      if(sheet.href && sheet.href.indexOf(stylesheet) != -1){
      rules = sheet[document.all ? 'rules' : 'cssRules'];
      for(var n in rules){
        console.log(rules[n].selectorText);
        if(rules[n].selectorText == selectorText){
          CCSstyle = rules[n].style;
          break;
        }
      }
      break;
      }
    }
    if(value == undefined)
      return CCSstyle[style]
    else
      return CCSstyle[style] = value
  }
//---------------------------------------------------------------------------------------------------------
- var translatePath = function(filePath, region) {
-   filePath = filePath.trim();
-   var regionPad = (region && region.length) ? '-' + region.toString() : '';
-   var matches = /{(.*)}.*/.exec(filePath);
-   if (matches) {
-     var topLevelDir = matches[1];
-     var currentPath = current.path;
-     var subPaths = currentPath.slice(2);
-     // subPaths[subPaths.length - 1] = "_." + subPaths[subPaths.length - 1];
-     subPaths[subPaths.length - 1] = "_fragments/" + subPaths[subPaths.length - 1];
-     var newPath = getPathToDocs() + topLevelDir + '/' + subPaths.join("/");
-     var result = newPath + regionPad + ".jade";
-   } else {
-     var extn = getExtn(filePath);
-     var baseFileName = getBaseFileName(filePath);
-     var noExtnFileName = baseFileName.substr(0,baseFileName.length - (extn.length + 1));
-     var folder = getFolder(filePath);
-     // var result = folder + "/_." + noExtnFileName + regionPad + "." + extn;
-     var result = folder + "/_fragments/" + noExtnFileName + regionPad + "." + extn;
-   }
-   return result
- }


- var EMPTY_STRINGS = [ '','','','','','',''];

- var strSplit = function(str, length) {
-   var res;
-   str = str || '';
-   if (!length) {
-     res = str.split(",");
-   } else {
-     res = str.split(",");
-     if (res.length < length) {
-       res = res.concat(EMPTY_STRINGS.slice(0, length - res.length));
-     }
-   }
-   return res;
- }

- var getFrag = function(filePath, region) {
-   var fullFileName = getFragFilePath(filePath, region);
-   var frag = partial(fullFileName);
-   if (frag == null) {
-     return "出错的文件: " + fullFileName + "   所在路径: " + current.path +  " 文档路径: " + getPathToDocs();
-   } else {
-     // ``` gets translated to <pre><code>.....</code></pre> and we need
-     // to remove this from the fragment prefix is 11 long and suffix is 13 long
-     frag = frag.substring(11, frag.length-13);
-     // Uncomment next line for debugging.
-     // frag = "FileName: " + fullFileName + "   Current path: " + current.path +  " PathToDocs: " + getPathToDocs() + "\n" + frag;
-     return frag;
-   }
- }

- var extractJson = function(json, jsonConfig ) {
-   try {
-     if (jsonConfig) {
-       return extractJsonFragment(json, jsonConfig.rootPath || null, jsonConfig.paths || [], jsonConfig.space || "  ");
-     } else {
-       return json;
-     }
-   } catch (e) {
-     return "ERROR";
-     // return json;
-   }
- }

- var unescapeHtml = function(s) {
-   // can't break across multiple lines because of jade limitations.
-   return s.replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '"').replace(/&#039/g, "'");
- }

- var styleString = function(source, stylePatterns) {
-   if (stylePatterns) {
-      for (var styleName in stylePatterns) {
-        var rxs = stylePatterns[styleName];
-        rxs = Array.isArray(rxs) ? rxs : [rxs];
-        rxs.forEach(function(rx) {
-          source = applyStyle(source, styleName, rx );
-        });
-      }
-   }
-  return source;
- }


- var getFragFilePath = function (filePath, region) {
-   filePath = filePath.trim();
-   var extn = getExtn(filePath);
-   var fileBase = filePath.substr(0,filePath.length - (extn.length + 1));
-   var regionPad = (region && region.length) ? '-' + region.toString() : '';
-   var fullFileName = getPathToFrags() + fileBase + regionPad + "." + extn + '.md';
-   return fullFileName;
- }

//- styles a string according to a regular expression.
//- The match groups resulting from the regexp application are what is styled
//- (not the whole regexp).
- var applyStyle = function(str, styleName, rx) {
-   var repls = {};
-   var matches;
-   do {
-     matches = rx.exec(str);
-     if (matches) {
-       matches.slice(1).forEach(function(match) {
-         var repl = '<span class="' + styleName + '">' + match + '</span>';
-         repls[match] = { repl: repl, isGlobal: rx.global };
-       });
-     }
-   } while (matches != null && rx.global );
-   for (var match in repls) {
-     var repl = repls[match];
-     // var escapedMatch = match.replace(/\\/g,'\\').replace(/\(/g,'\(').replace(/\)/g, '\)').replace(/\./,'\.');
-     // var rx2 = new RegExp(escapedMatch, repl.isGlobal ? "g" : "");
-     var rx2 = match;
-     str = str.replace(rx2, repl.repl);
-   };
-   return str;
- }

- var getExtn = function(fileName) {
-   var ix = fileName.lastIndexOf('.');
-   return ix > 0 ? fileName.substr(ix+1) : "";
- }

- var getBaseFileName = function(fileName) {
-   var ix = fileName.lastIndexOf('/');
-   return ix > 0 ? fileName.substr(ix+1) : "";
- }

- var getFolder = function(fileName) {
-   var ix = fileName.lastIndexOf('/');
-   return ix > 0 ? fileName.substr(0, ix) : "";
- }

- var getPathToDocs = function() {
-   // simple way to only take as many '../' sections as we need to back up to the 'docs' dir
-   // from the current document
-   // we will almost certainly never go 10 or 11 deep but ...
-   return current.pathToDocs || "../../../../../../../../../../../".substr(0, (current.path.length-2)*3);
- }

- var getPathToFrags = function() {
-   return getPathToDocs() + "_fragments/";
- }

- var getPathToExamples = function() {
-   return getPathToDocs() + "_examples/";
- }

//- Extract a subset of a json file in a specified order defined
//- by extractPaths while retaining original order for any
//- unspecified subobjects.
//-
//- based on the principle that JSON.parse(source) constructs objects
//- in order from the top down in 'source' and JSON.stringify(source) iterates 'source'
//- properties according to the order in which they were inserted.  ( the spec actually
//- discourages this assumption but this method will only
//- run on node (v8) and the assumption seems safe there. )
- function extractJsonFragment(source, rootPath, extractPaths, space) {
-   var objSource = JSON.parse(source);
-   if (rootPath && rootPath.length > 0) {
-     objSource = getSubObject(objSource, rootPath);
-   }
-   var objDest = {};
-   extractPaths.trim().split(",").forEach(function(dotPath) {
-     processPath(objSource, objDest, dotPath );
-   });
-   var result = JSON.stringify(objDest, null, space || "  ");
-   return result;

-   function getSubObject(source, path) {
-     var nextSource = source;
-     var pathParts = path.trim().split(".");
-     while (pathParts.length > 0) {
-       var nextProp = pathParts.shift();
-       nextSource = nextSource[nextProp];
-     }
-     return nextSource;
-   }

-   function processPath(source, dest, dotPath) {
-     var nextSource = source;
-     var nextDest = dest;
-     var pathParts = dotPath.trim().split(".");
-     while (pathParts.length > 0) {
-       var nextProp = pathParts.shift();
-       nextSource = nextSource[nextProp];
-       if (pathParts.length > 0) {
-         var val = nextDest[nextProp] || {};
-         nextDest[nextProp] = val;
-         nextDest = val;
-       } else {
-         nextDest[nextProp] = nextSource;
-       }
-     }
-   }
- }
