import _classCallCheck from '@babel/runtime/helpers/classCallCheck';
import _createClass from '@babel/runtime/helpers/createClass';
import { getFs } from '../nodejs/fs.mjs';
import { getPath } from '../nodejs/path.mjs';
import { getCheerio } from '../third-party/cheerio.mjs';
import { timeStampFormat } from '../time/time.mjs';

var DEFAULT_EXTRA_CSS = "\n.nav-separator {\n  color: hsl(207, 1%, 60%);\n  font-size: 12px;\n  display: block;\n}\n\nnav ul a, nav ul a:active {\n  font-size: 14px;\n}\n";
function getSeparatorStr(content) {
  var maxLen = 14;
  var lastLen = parseInt("".concat(maxLen - content.length / 2), 10);
  var fill = Array.from({
    length: lastLen
  }).map(function () {
    return '-';
  }).join('');
  return "".concat(fill, "   ").concat(content, "   ").concat(fill);
}
/**
 * 删除重复的部分
 * @ignore
 */
function deleteRepeatedSections($) {
  var sections = $('section');
  var last = '';
  sections.map(function (_, section) {
    var html = $(section).html().trim();
    if (html === last) {
      $(section).remove();
    } else {
      last = html;
    }
  });
  return $;
}
/**
 * 替换footer
 * @ignore
 * @param $ cheerio
 * @param author 作者
 */
function replaceFooter($, author) {
  var timezone = new Date().getTimezoneOffset() / -60;
  var footerContent = "Documentation generated on ".concat(timeStampFormat(Date.now(), 'yyyy-MM-dd hh:mm:ss'), " GMT+0").concat(timezone, "00 ").concat(author && " by ".concat(author), ".");
  $('footer').html(footerContent);
}
/**
 * 找到 Modules 下的导航列表
 * @ignore
 * @param $ cheerio
 */
function findModuleNav($) {
  var titles = $('body nav h3');
  var res;
  titles.map(function (_, title) {
    if ($(title).html().trim() === 'Modules') {
      res = $(title).next();
    }
  });
  return res;
}
/**
 * 获取nav头部，比如 tools/url => tools
 * @ignore
 * @example
 * ```ts
 * getNavPrefix('tools/url'); // 'tools'
 * getNavPrefix('url');       // ''
 * ```
 */
function getNavPrefix() {
  var nav = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
  if (nav.indexOf('/') < 0) {
    return '';
  }
  return nav.split('/')[0];
}
/**
 * 给 Modules 下的导航列表插入分隔符
 * @ignore
 * @param $ cheerio
 */
function insertModuleNavSeparator($) {
  var module = findModuleNav($);
  if (!module) return;
  var last = '';
  $(module).children('li').map(function (_, li) {
    var _a, _b;
    var nav = (_b = (_a = $(li).children('a')) === null || _a === void 0 ? void 0 : _a.html()) === null || _b === void 0 ? void 0 : _b.trim();
    var prefix = getNavPrefix(nav);
    if (prefix && last !== prefix) {
      $(li).before("<li class=\"nav-separator\">".concat(getSeparatorStr(prefix), "</li>"));
    }
    if (prefix) {
      last = prefix;
      var navList = nav.split('/');
      $(li).children('a').html(navList.slice(1).join('/'));
    }
  });
}
/**
 * 插入分隔符
 * @ignore
 */
function insertNavSeparator($, sourceMap) {
  var naves = $('nav > ul li');
  var cur = '';
  naves.map(function (_, dom) {
    var _a;
    var nav = (_a = $(dom).find('a').attr('href')) === null || _a === void 0 ? void 0 : _a.trim();
    if (nav && sourceMap[nav] && cur !== sourceMap[nav]) {
      $(dom).before("<li class=\"nav-separator\">".concat(sourceMap[nav], "</li>"));
      cur = sourceMap[nav];
    }
  });
}
/**
 * 插入script
 * @ignore
 */
function insertScript($) {
  var script = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
  if (!script) return;
  $('head').children().last().after(script);
}
/**
 * 默认处理source的方法，默认仅去掉的文件名
 * @ignore
 * @param source 文件路径
 * @returns 处理后的数据
 * @example
 * ```ts
 * defaultNavHandler('base/url/url.ts');
 * // 'base/url'
 * ```
 */
function defaultNavHandler(source) {
  var list = source.split('/');
  return list.slice(0, list.length - 1).join('/');
}
var JsDocHandler = /*#__PURE__*/function () {
  /**
   * 处理jsdoc的脚本
   * 1. 增加导航栏的分隔符
   * 2. 增加css
   * 3. 处理footer
   * @constructor
   * @param {object} options 配置
   * @param {string} [options.docsPath] 文档所在目录位置，默认为`./docs`
   * @param {string} [options.author] 作者，默认为空
   * @param {string} [options.extraCss] 额外插入的css，默认为`.nav-separator`的一些样式
   * @param {string} [options.extraScript] 额外插入的script
   * @param {Function} [options.navHandler] 处理API所在文件的方法
   * @param {boolean} [options.isHandleNav] 是否处理导航栏，即插入文件名进行分隔，默认为false
   */
  function JsDocHandler() {
    var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
    _classCallCheck(this, JsDocHandler);
    var _options$docsPath = options.docsPath,
      docsPath = _options$docsPath === void 0 ? './docs' : _options$docsPath,
      _options$author = options.author,
      author = _options$author === void 0 ? '' : _options$author,
      _options$extraCss = options.extraCss,
      extraCss = _options$extraCss === void 0 ? DEFAULT_EXTRA_CSS : _options$extraCss,
      _options$extraScript = options.extraScript,
      extraScript = _options$extraScript === void 0 ? '' : _options$extraScript,
      _options$navHandler = options.navHandler,
      navHandler = _options$navHandler === void 0 ? defaultNavHandler : _options$navHandler,
      _options$isHandleNav = options.isHandleNav,
      isHandleNav = _options$isHandleNav === void 0 ? false : _options$isHandleNav;
    this.docsPath = docsPath;
    this.author = author;
    this.extraCss = extraCss;
    this.extraScript = extraScript;
    this.navHandler = navHandler;
    this.isHandleNav = isHandleNav;
    this.fs = this.getFs();
    this.path = getPath();
  }
  return _createClass(JsDocHandler, [{
    key: "run",
    value: function run() {
      var sourceMap = {};
      if (this.isHandleNav) {
        sourceMap = this.getGlobalSourceMap();
      }
      this.handleEveryHtml(sourceMap, this.author);
      this.appendCSS(this.extraCss);
      this.finished();
    }
  }, {
    key: "getFs",
    value: function getFs$1() {
      return getFs();
    }
  }, {
    key: "getGlobalSourceMap",
    value: function getGlobalSourceMap() {
      console.log('[Jsdoc] Parsing nav list of global.html ...');
      var file = 'global.html';
      var sourceMap = this.getSourceMap(file);
      return this.parseSourceMap(sourceMap);
    }
    /**
     * 获取sourceMap，形如：
     * ```ts
     * {
     *   NUMBER_CHI_MAP: 'base/number/number.ts',
     *   parseFunction: 'base/function/function.ts',
     *   flatten: 'base/list/list.ts',
     * }
     * ```
     * @private
     * @param {string} content
     * @returns {object} sourceMap
     */
  }, {
    key: "getSourceMap",
    value: function getSourceMap(file) {
      var _this = this;
      var html = this.path.resolve(this.docsPath, file);
      var content = this.fs.readFileSync(html, {
        encoding: 'utf-8'
      });
      var cheerio = getCheerio();
      var $ = cheerio.load(content);
      var sourceMap = {};
      var names = $('#main section article h4.name');
      names.map(function (_, dom) {
        var id = $(dom).attr('id');
        var source = ($(dom).next().find('dd.tag-source ul.dummy li a').html() || '').trim();
        source = _this.navHandler(source);
        sourceMap["".concat(file, "#").concat(id)] = source;
      });
      return sourceMap;
    }
  }, {
    key: "handleEveryHtml",
    value: function handleEveryHtml(sourceMap, author) {
      var _this2 = this;
      var files = this.fs.readdirSync(this.docsPath);
      files.forEach(function (file) {
        if (file.endsWith('.html')) {
          var filePath = _this2.path.resolve(_this2.docsPath, file);
          var content = _this2.fs.readFileSync(filePath, {
            encoding: 'utf-8'
          });
          var html = _this2.getParsedHtml(content, sourceMap, author);
          _this2.fs.writeFileSync(filePath, html, {
            encoding: 'utf-8'
          });
        }
      });
    }
  }, {
    key: "parseSourceMap",
    value: function parseSourceMap(sourceMap) {
      return Object.keys(sourceMap).reduce(function (acc, key) {
        var value = sourceMap[key];
        acc[key] = getSeparatorStr(value);
        return acc;
      }, {});
    }
  }, {
    key: "getParsedHtml",
    value: function getParsedHtml(content, sourceMap, author) {
      var cheerio = getCheerio();
      var $ = cheerio.load(content);
      var extraScript = this.extraScript;
      // 删除重复selection
      deleteRepeatedSections($);
      // 插入分隔符
      insertNavSeparator($, sourceMap);
      // Modules下的导航栏插入分隔符
      insertModuleNavSeparator($);
      // 插入script
      insertScript($, extraScript);
      // 处理footer
      replaceFooter($, author);
      return $.html();
    }
  }, {
    key: "appendCSS",
    value: function appendCSS(extra) {
      console.log('[Jsdoc] Appending extra css ...');
      var css = this.path.resolve(this.docsPath, 'styles/jsdoc.css');
      var content = this.fs.readFileSync(css, {
        encoding: 'utf-8'
      });
      this.fs.writeFileSync(css, "".concat(content, " \n").concat(extra), {
        encoding: 'utf-8'
      });
    }
  }, {
    key: "finished",
    value: function finished() {
      console.log('[Jsdoc] Finished jsdoc local script.');
    }
  }], [{
    key: "init",
    value:
    /**
     * 初始化并运行
     * @static
     * @param {object} options 配置
     * @param {string} [options.docsPath] 文档所在目录位置，默认为`./docs`
     * @param {string} [options.author] 作者，默认为空
     * @param {string} [options.extraCss] 额外插入的css，默认为`.nav-separator`的一些样式
     * @param {string} [options.navHandler] 处理API所在文件的方法
     * @param {boolean} [options.isHandleNav] 是否处理导航栏，即插入文件名进行分隔，默认为false
     * @returns {object} JsDocHandler实例
     * @example
     *
     * JsDocHandler.init({
     *   author: 'novlan1',
     *   docsPath: './docs',
     *   extraCss: '.some-class{}',
     *   navHandler(nav) {
     *
     *   }
     * })
     *
     */
    function init(options) {
      var handler = new JsDocHandler(options);
      handler.run();
      return handler;
    }
  }]);
}();

export { JsDocHandler, defaultNavHandler, getNavPrefix, getSeparatorStr };
