import {Stats} from "./stats.js";
function _defineProperty(obj, key, value) {
  if (key in obj) {
    Object.defineProperty(obj, key, {
      value,
      enumerable: true,
      configurable: true,
      writable: true
    });
  } else {
    obj[key] = value;
  }
  return obj;
}
const KB = 1024;
const MB = 1024 * KB;
const GB = 1024 * MB;
function formatTime(t) {
  let value;
  let unit;
  let precision;
  if (t < 1) {
    value = t * 1e3;
    unit = "\u03BCs";
    precision = 0;
  } else if (t < 1e3) {
    value = t;
    unit = "ms";
    precision = 2;
  } else {
    value = t / 1e3;
    unit = "s";
    precision = 2;
  }
  return "".concat(value.toFixed(precision)).concat(unit);
}
function formatMemory(b) {
  let value;
  let unit;
  let precision;
  if (b < KB) {
    value = b;
    unit = " bytes";
    precision = 0;
  } else if (b < MB) {
    value = b / KB;
    unit = "kB";
    precision = 2;
  } else if (b < GB) {
    value = b / MB;
    unit = "MB";
    precision = 2;
  } else {
    value = b / GB;
    unit = "GB";
    precision = 2;
  }
  return "".concat(value.toFixed(precision)).concat(unit);
}
const RIGHT_ARROW = "\u25B6";
const DOWN_ARROW = "\u2B07";
const DEFAULT_CSS = {
  css: {
    position: "fixed",
    zIndex: 1e4,
    color: "#ccc",
    background: "#000",
    fontFamily: "Helvetica,Arial,sans-serif",
    padding: "8px",
    fontSize: "12px",
    lineSpacing: 6
  },
  headerCSS: {
    fontSize: "16px",
    cursor: "pointer"
  },
  itemCSS: {
    paddingLeft: "8px"
  }
};
const DEFAULT_FORMATTERS = {
  count: (stat) => "".concat(stat.name, ": ").concat(stat.count),
  averageTime: (stat) => "".concat(stat.name, ": ").concat(formatTime(stat.getAverageTime())),
  totalTime: (stat) => "".concat(stat.name, ": ").concat(formatTime(stat.time)),
  fps: (stat) => "".concat(stat.name, ": ").concat(Math.round(stat.getHz()), "fps"),
  memory: (stat) => "".concat(stat.name, ": ").concat(formatMemory(stat.count))
};
class StatsWidget {
  constructor(stats2, options) {
    _defineProperty(this, "stats", void 0);
    _defineProperty(this, "title", void 0);
    _defineProperty(this, "collapsed", false);
    _defineProperty(this, "_framesPerUpdate", void 0);
    _defineProperty(this, "_formatters", DEFAULT_FORMATTERS);
    _defineProperty(this, "_css", void 0);
    _defineProperty(this, "_headerCSS", void 0);
    _defineProperty(this, "_itemCSS", void 0);
    _defineProperty(this, "_container", null);
    _defineProperty(this, "_innerContainer", null);
    _defineProperty(this, "_statsContainer", null);
    _defineProperty(this, "_header", null);
    _defineProperty(this, "_resetOnUpdate", {});
    _defineProperty(this, "_counter", 0);
    _defineProperty(this, "_items", {});
    _defineProperty(this, "_added", false);
    this.stats = stats2;
    this.title = options === null || options === void 0 ? void 0 : options.title;
    this._framesPerUpdate = Math.round(Math.max((options === null || options === void 0 ? void 0 : options.framesPerUpdate) || 1, 1));
    this._initializeFormatters(options);
    this._initializeUpdateConfigs(options);
    this._css = Object.assign({}, DEFAULT_CSS.css, options === null || options === void 0 ? void 0 : options.css);
    this._headerCSS = Object.assign({}, DEFAULT_CSS.headerCSS, this._css.header);
    this._itemCSS = Object.assign({}, DEFAULT_CSS.itemCSS, this._css.item);
    delete this._css.header;
    delete this._css.item;
    this._createDOM(options === null || options === void 0 ? void 0 : options.container);
    this._createDOMStats();
  }
  setStats(stats2) {
    this.stats = stats2;
    this._createDOMStats();
    this._setHeaderContent();
    this.update();
  }
  update() {
    const stats2 = this.stats && this.stats.stats;
    if (!stats2 || Object.keys(stats2).length === 0) {
      return;
    }
    if (this._counter++ % this._framesPerUpdate !== 0) {
      return;
    }
    this._update();
  }
  remove() {
    this._container.removeChild(this._innerContainer);
  }
  setCollapsed(collapsed) {
    this.collapsed = collapsed;
    if (this._statsContainer) {
      this._statsContainer.style.display = this.collapsed ? "none" : "block";
    }
    this._setHeaderContent();
  }
  _update() {
    this.stats.forEach((stat) => {
      this._createDOMItem(stat.name);
      this._items[stat.name].innerHTML = this._getLines(stat).join("<BR>");
      if (this._resetOnUpdate[stat.name]) {
        stat.reset();
      }
    });
  }
  _initializeFormatters(options) {
    if (options !== null && options !== void 0 && options.formatters) {
      for (const name in options.formatters) {
        let formatter = options.formatters[name];
        if (typeof formatter === "string") {
          formatter = DEFAULT_FORMATTERS[formatter];
        }
        this._formatters[name] = formatter;
      }
    }
  }
  _initializeUpdateConfigs(options) {
    if (options !== null && options !== void 0 && options.resetOnUpdate) {
      for (const name in options.resetOnUpdate) {
        this._resetOnUpdate[name] = options.resetOnUpdate[name];
      }
    }
  }
  _createDOM(container) {
    if (typeof document === "undefined" || !document) {
      return;
    }
    this._container = container;
    if (!this._container) {
      this._container = document.createElement("div");
      for (const name in this._css) {
        this._container.style[name] = this._css[name];
      }
      document.body.appendChild(this._container);
    }
    this._innerContainer = document.createElement("div");
    this._container.appendChild(this._innerContainer);
    this._createDOMHeader();
    this._statsContainer = document.createElement("div");
    this._statsContainer.style.display = "block";
    this._innerContainer.appendChild(this._statsContainer);
  }
  _createDOMHeader() {
    if (!this._header) {
      this._header = document.createElement("div");
      for (const name in this._headerCSS) {
        this._header.style[name] = this._headerCSS[name];
      }
      this._header.onclick = this._toggleCollapsed.bind(this);
      this._innerContainer.appendChild(this._header);
    }
    this._setHeaderContent();
  }
  _setHeaderContent() {
    if (this._header) {
      const collapsedState = this.collapsed ? RIGHT_ARROW : DOWN_ARROW;
      const title = this.title || this.stats && this.stats.id || "Stats";
      this._header.innerText = "".concat(collapsedState, " ").concat(title);
    }
  }
  _toggleCollapsed() {
    this.setCollapsed(!this.collapsed);
  }
  _createDOMStats() {
    if (this.stats instanceof Stats) {
      this.stats.forEach((stat) => {
        this._createDOMItem(stat.name);
      });
    }
  }
  _createDOMItem(statName) {
    if (!this._statsContainer) {
      return;
    }
    if (this._items[statName]) {
      return;
    }
    this._items[statName] = document.createElement("div");
    for (const name in this._itemCSS) {
      this._items[statName].style[name] = this._itemCSS[name];
    }
    this._statsContainer.appendChild(this._items[statName]);
  }
  _getLines(stat) {
    const formatter = this._formatters[stat.name] || this._formatters[stat.type] || DEFAULT_FORMATTERS.count;
    return formatter(this.stats.get(stat.name)).split("\n");
  }
}
export default StatsWidget;
export {StatsWidget};