(function () {
  "use strict";

  if (!Array.from) {
    Array.from = function (value) {
      return Array.prototype.slice.call(value || []);
    };
  }

  if (!Array.prototype.flat) {
    Object.defineProperty(Array.prototype, "flat", {
      value: function (depth) {
        var maxDepth = depth === undefined ? 1 : Number(depth) || 0;
        var flatten = function (items, level) {
          return items.reduce(function (result, item) {
            if (Array.isArray(item) && level > 0) {
              return result.concat(flatten(item, level - 1));
            }
            result.push(item);
            return result;
          }, []);
        };
        return flatten(this, maxDepth);
      }
    });
  }

  if (!Array.prototype.flatMap) {
    Object.defineProperty(Array.prototype, "flatMap", {
      value: function (callback, thisArg) {
        return Array.prototype.map.call(this, callback, thisArg).flat();
      }
    });
  }

  if (!Object.values) {
    Object.values = function (object) {
      return Object.keys(object || {}).map(function (key) {
        return object[key];
      });
    };
  }

  if (!Object.entries) {
    Object.entries = function (object) {
      return Object.keys(object || {}).map(function (key) {
        return [key, object[key]];
      });
    };
  }

  if (!Object.fromEntries) {
    Object.fromEntries = function (entries) {
      var object = {};
      Array.from(entries || []).forEach(function (entry) {
        if (entry && entry.length >= 2) object[entry[0]] = entry[1];
      });
      return object;
    };
  }

  if (!String.prototype.padStart) {
    Object.defineProperty(String.prototype, "padStart", {
      value: function (length, fill) {
        var text = String(this);
        var pad = fill === undefined ? " " : String(fill);
        if (!pad) pad = " ";
        while (text.length < length) text = pad + text;
        return text.slice(-length);
      }
    });
  }

  if (!String.prototype.includes) {
    Object.defineProperty(String.prototype, "includes", {
      value: function (search, start) {
        return this.indexOf(search, start || 0) !== -1;
      }
    });
  }

  if (!String.prototype.startsWith) {
    Object.defineProperty(String.prototype, "startsWith", {
      value: function (search, position) {
        return this.substr(position || 0, String(search).length) === String(search);
      }
    });
  }

  if (!Number.isFinite) {
    Number.isFinite = function (value) {
      return typeof value === "number" && isFinite(value);
    };
  }

  if (window.Element && !Element.prototype.matches) {
    Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
  }

  if (window.Element && !Element.prototype.closest) {
    Element.prototype.closest = function (selector) {
      var node = this;
      while (node && node.nodeType === 1) {
        if (node.matches && node.matches(selector)) return node;
        node = node.parentElement || node.parentNode;
      }
      return null;
    };
  }

  if (window.NodeList && !NodeList.prototype.forEach) {
    NodeList.prototype.forEach = Array.prototype.forEach;
  }
})();
