var __extends =
  (this && this.__extends) ||
  (function () {
    var extendStatics = function (d, b) {
      extendStatics =
        Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array &&
          function (d, b) {
            d.__proto__ = b;
          }) ||
        function (d, b) {
          for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
        };
      return extendStatics(d, b);
    };
    return function (d, b) {
      extendStatics(d, b);
      function __() {
        this.constructor = d;
      }
      d.prototype =
        b === null
          ? Object.create(b)
          : ((__.prototype = b.prototype), new __());
    };
  })();
var lv = /** @class */ (function () {
  function lv() {
    this.observer = new MutationObserver(this.callback);
  }
  /**
   * iterates through all elements and calls function create on them
   */
  lv.prototype.initLoaderAll = function () {
    var divs = document.getElementsByTagName("DIV");
    for (var i = 0; i < divs.length; i++) {
      if (!divs[i].hasChildNodes()) {
        lv.create(divs[i]);
      }
    }
  };
  /**
   * returns list of non-main classes (every except the one that specifies the element)
   * @param classList
   * @param notIncludingClass
   */
  lv.getModifyingClasses = function (classList, notIncludingClass) {
    var modifyingClasses = [];
    for (var i = 0; i < classList.length; i++) {
      if (classList[i] != notIncludingClass) {
        modifyingClasses.push(classList[i]);
      }
    }
    return modifyingClasses;
  };
  /**
   * decides type of passed element and returns its object
   * @param element - pass existing element or null
   * @param classString - classes separated with one space that specifies type of element, optional, only when passing null instead of element
   */
  lv.create = function (element, classString) {
    if (element === void 0) {
      element = null;
    }
    var classes = [];
    if (element != null) {
      var listOfClasses = element.classList;
      for (var i = 0; i < listOfClasses.length; i++) {
        classes.push(listOfClasses[i]);
      }
    } else if (classString != null) {
      classes = classString.split(" ");
    }
    for (var i = 0; i < classes.length; i++) {
      switch (classes[i]) {
        case "lv-bars":
          return new lv.Circle(
            element,
            lv.CircleType.Bars,
            lv.getModifyingClasses(classes, "lv-bars")
          );
        case "lv-squares":
          return new lv.Circle(
            element,
            lv.CircleType.Squares,
            lv.getModifyingClasses(classes, "lv-squares")
          );
        case "lv-circles":
          return new lv.Circle(
            element,
            lv.CircleType.Circles,
            lv.getModifyingClasses(classes, "lv-circles")
          );
        case "lv-dots":
          return new lv.Circle(
            element,
            lv.CircleType.Dots,
            lv.getModifyingClasses(classes, "lv-dots")
          );
        case "lv-spinner":
          return new lv.Circle(
            element,
            lv.CircleType.Spinner,
            lv.getModifyingClasses(classes, "lv-spinner")
          );
        case "lv-dashed":
          return new lv.Circle(
            element,
            lv.CircleType.Dashed,
            lv.getModifyingClasses(classes, "lv-dashed")
          );
        case "lv-determinate_circle":
          return new lv.Circle(
            element,
            lv.CircleType.DeterminateCircle,
            lv.getModifyingClasses(classes, "lv-determinate_circle")
          );
        case "lv-line":
          return new lv.Bar(
            element,
            lv.BarType.Line,
            lv.getModifyingClasses(classes, "lv-line")
          );
        case "lv-bordered_line":
          return new lv.Bar(
            element,
            lv.BarType.BorderedLine,
            lv.getModifyingClasses(classes, "lv-bordered_line")
          );
        case "lv-determinate_line":
          return new lv.Bar(
            element,
            lv.BarType.DeterminateLine,
            lv.getModifyingClasses(classes, "lv-determinate_line")
          );
        case "lv-determinate_bordered_line":
          return new lv.Bar(
            element,
            lv.BarType.DeterminateBorderedLine,
            lv.getModifyingClasses(classes, "lv-determinate_bordered_line")
          );
      }
    }
    return null;
  };
  /**
   * observes for changes in DOM and creates new element's objects
   * @param mutationList
   * @param observer
   */
  lv.prototype.callback = function (mutationList, observer) {
    for (var i = 0; i < mutationList.length; i++) {
      if (mutationList[i].type === "childList") {
        try {
          if (mutationList[i].addedNodes[0].classList.length > 0) {
            // filling the node with divs when it is empty
            lv.create(mutationList[i].addedNodes[0]);
          }
        } catch (error) {}
      }
    }
  };
  lv.prototype.startObserving = function () {
    this.observer.observe(document.body, { childList: true, subtree: true });
  };
  lv.prototype.stopObserving = function () {
    this.observer.disconnect();
  };
  return lv;
})();
(function (lv) {
  /**
   * specifies functions same for all elements
   */
  var ElementBase = /** @class */ (function () {
    function ElementBase(element) {
      this.element = element === null ? document.createElement("div") : element;
    }
    ElementBase.prototype.show = function () {
      this.element.style.display = null;
    };
    ElementBase.prototype.hide = function () {
      this.element.style.display = "none";
    };
    ElementBase.prototype.remove = function () {
      this.element.parentNode.removeChild(this.element);
    };
    ElementBase.prototype.setLabel = function (labelText) {
      this.element.setAttribute("data-label", labelText);
    };
    ElementBase.prototype.removeLabel = function () {
      this.element.removeAttribute("data-label");
    };
    ElementBase.prototype.showPercentage = function () {
      this.element.setAttribute("data-percentage", "true");
    };
    ElementBase.prototype.hidePercentage = function () {
      this.element.removeAttribute("data-percentage");
    };
    ElementBase.prototype.setId = function (idText) {
      this.element.setAttribute("id", idText);
    };
    ElementBase.prototype.removeId = function () {
      this.element.removeAttribute("id");
    };
    /**
     * adds class or classes to element
     * @param classString - string that contains classes separated with one space
     */
    ElementBase.prototype.addClass = function (classString) {
      var classList = classString.split(" ");
      for (var i = 0; i < classList.length; i++) {
        this.element.classList.add(classList[i]);
      }
    };
    /**
     * if element contains specified class or classes, it/they are removed
     * @param classString - string that contains classes separated with one space
     */
    ElementBase.prototype.removeClass = function (classString) {
      var classList = classString.split(" ");
      for (var i = 0; i < classList.length; i++) {
        if (this.element.classList.contains(classList[i])) {
          this.element.classList.remove(classList[i]);
        }
      }
    };
    /**
     * returns DOM element - needed for placing or removing the element with jquery
     */
    ElementBase.prototype.getElement = function () {
      return this.element;
    };
    /**
     * resets determinate element to 0
     * @param maxValue
     */
    ElementBase.prototype.reset = function (maxValue) {
      this.update("set", 0, maxValue);
    };
    /**
     * sets determinate element to 100%
     * @param maxValue
     */
    ElementBase.prototype.fill = function (maxValue) {
      this.update("set", maxValue, maxValue);
    };
    /**
     * adds positive or negative value to a determinate element
     * @param addValue
     * @param maxValue
     */
    ElementBase.prototype.add = function (addValue, maxValue) {
      this.update("add", addValue, maxValue);
    };
    /**
     * sets loading bar to passed value
     * @param value
     * @param maxValue
     */
    ElementBase.prototype.set = function (value, maxValue) {
      this.update("set", value, maxValue);
    };
    /**
     * initializes an element
     * @param loaderElement
     * @param description
     */
    ElementBase.prototype.initLoader = function (loaderElement, description) {
      // manual addition on specified object
      if (!loaderElement.hasChildNodes()) {
        this.fillElement(
          loaderElement,
          description.className,
          description.divCount
        );
      }
    };
    /**
     * fills element with appropriate number of divs
     * @param element
     * @param elementClass
     * @param divNumber
     */
    ElementBase.prototype.fillElement = function (
      element,
      elementClass,
      divNumber
    ) {
      for (var i = 0; i < divNumber; i += 1) {
        element.appendChild(document.createElement("DIV"));
      }
      if (
        elementClass === "lv-determinate_circle" ||
        elementClass === "lv-determinate_line" ||
        elementClass === "lv-determinate_bordered_line"
      ) {
        element.lastElementChild.innerHTML = "0";
      }
      if (!element.classList.contains(elementClass)) {
        element.classList.add(elementClass);
      }
    };
    return ElementBase;
  })();
  lv.ElementBase = ElementBase;
  /**
   * class for linear elements
   */
  var Bar = /** @class */ (function (_super) {
    __extends(Bar, _super);
    /**
     * creates linear element
     * @param element
     * @param barType
     * @param classes
     */
    function Bar(element, barType, classes) {
      if (classes === void 0) {
        classes = null;
      }
      var _this = _super.call(this, element) || this;
      _this.divCount = {};
      _this.divCount[BarType.Line] = { className: "lv-line", divCount: 1 };
      _this.divCount[BarType.BorderedLine] = {
        className: "lv-bordered_line",
        divCount: 1,
      };
      _this.divCount[BarType.DeterminateLine] = {
        className: "lv-determinate_line",
        divCount: 2,
      };
      _this.divCount[BarType.DeterminateBorderedLine] = {
        className: "lv-determinate_bordered_line",
        divCount: 2,
      };
      _this.initLoader(_this.element, _this.divCount[barType]);
      for (var i = 0; i < classes.length; i++) {
        _this.element.classList.add(classes[i]);
      }
      return _this;
    }
    /**
     * type specific update function for linear element
     * @param type
     * @param newValue
     * @param maxValue
     */
    Bar.prototype.update = function (type, newValue, maxValue) {
      // getting current width of line from the page
      var line = this.element.firstElementChild;
      var percentage = this.element.lastElementChild;
      var currentWidth = parseFloat(line.style.width);
      // protective condition for empty line
      if (isNaN(currentWidth)) {
        currentWidth = 0;
      }
      // end point of the animation
      var goalWidth;
      if (type === "add") {
        goalWidth =
          currentWidth + Math.round((newValue / maxValue) * 1000) / 10;
      } else if (type === "set") {
        goalWidth = Math.round((newValue / maxValue) * 1000) / 10;
      }
      // prevent overflow from both sides
      if (goalWidth > 100) {
        goalWidth = 100.0;
      }
      if (goalWidth < 0) {
        goalWidth = 0;
      }
      var animation = setInterval(frame, 5);
      function frame() {
        if (currentWidth > goalWidth) {
          // shortening the line
          if (currentWidth < goalWidth + 0.01) {
            clearInterval(animation);
          } else {
            currentWidth -= 0.1;
          }
        } else {
          // extending the line
          if (currentWidth > goalWidth - 0.01) {
            clearInterval(animation);
          } else {
            currentWidth += 0.1;
          }
        }
        line.style.width = currentWidth + "%";
        // updating the percentage
        percentage.innerHTML = currentWidth.toFixed(1);
      }
    };
    return Bar;
  })(ElementBase);
  lv.Bar = Bar;
  /**
   * class for square or circular elements
   */
  var Circle = /** @class */ (function (_super) {
    __extends(Circle, _super);
    /**
     * creates square or circular element
     * @param element
     * @param circleType
     * @param classes
     */
    function Circle(element, circleType, classes) {
      if (classes === void 0) {
        classes = null;
      }
      var _this = _super.call(this, element) || this;
      _this.divCount = {};
      _this.divCount[CircleType.Bars] = { className: "lv-bars", divCount: 8 };
      _this.divCount[CircleType.Squares] = {
        className: "lv-squares",
        divCount: 4,
      };
      _this.divCount[CircleType.Circles] = {
        className: "lv-circles",
        divCount: 12,
      };
      _this.divCount[CircleType.Dots] = { className: "lv-dots", divCount: 4 };
      _this.divCount[CircleType.DeterminateCircle] = {
        className: "lv-determinate_circle",
        divCount: 4,
      };
      _this.divCount[CircleType.Spinner] = {
        className: "lv-spinner",
        divCount: 1,
      };
      _this.divCount[CircleType.Dashed] = {
        className: "lv-dashed",
        divCount: 1,
      };
      _this.initLoader(_this.element, _this.divCount[circleType]);
      for (var i = 0; i < classes.length; i++) {
        _this.element.classList.add(classes[i]);
      }
      return _this;
    }
    /**
     * type specific update function for non-linear elements
     * @param type
     * @param newValue
     * @param maxValue
     */
    Circle.prototype.update = function (type, newValue, maxValue) {
      var rotationOffset = -45; // initial rotation of the spinning div in css
      // separating individual parts of the circle
      var background = this.element.children[0];
      var overlay = this.element.children[1];
      var spinner = this.element.children[2];
      var percentage = this.element.children[3];
      // getting the colors defined in css
      var backgroundColor = window.getComputedStyle(background).borderTopColor;
      var spinnerColor = window.getComputedStyle(spinner).borderTopColor;
      // computing current rotation of spinning part of circle using rotation matrix
      var rotationMatrix = window
        .getComputedStyle(spinner)
        .getPropertyValue("transform")
        .split("(")[1]
        .split(")")[0]
        .split(",");
      var currentAngle =
        Math.round(
          Math.atan2(
            parseFloat(rotationMatrix[1]),
            parseFloat(rotationMatrix[0])
          ) *
            (180 / Math.PI)
        ) - rotationOffset;
      // safety conditions for full and empty circle (360 <=> 0 and that caused problems)
      if (percentage.innerHTML === "100") {
        currentAngle = 360;
      }
      if (currentAngle < 0) {
        currentAngle += 360;
      }
      // end point of the animation
      var goalAngle;
      if (type === "add") {
        goalAngle = currentAngle + Math.round((newValue / maxValue) * 360);
      } else if (type === "set") {
        goalAngle = Math.round((newValue / maxValue) * 360);
      }
      // prevent overflow to both sides
      if (goalAngle > 360) {
        goalAngle = 360;
      }
      if (goalAngle < 0) {
        goalAngle = 0;
      }
      var id = setInterval(frame, 3);
      function frame() {
        if (currentAngle === goalAngle) {
          // stopping the animation when end point is reached
          clearInterval(id);
        } else {
          if (currentAngle < goalAngle) {
            // "filling" the circle
            if (currentAngle === 90) {
              background.style.borderRightColor = spinnerColor;
              overlay.style.borderTopColor = "transparent";
            } else if (currentAngle === 180) {
              background.style.borderBottomColor = spinnerColor;
            } else if (currentAngle === 270) {
              background.style.borderLeftColor = spinnerColor;
            }
            currentAngle += 1;
          } else {
            // "emptying the circle"
            if (currentAngle === 270) {
              background.style.borderLeftColor = backgroundColor;
            } else if (currentAngle === 180) {
              background.style.borderBottomColor = backgroundColor;
            } else if (currentAngle === 90) {
              background.style.borderRightColor = backgroundColor;
              overlay.style.borderTopColor = backgroundColor;
            }
            currentAngle -= 1;
          }
          // rotating the circle
          spinner.style.transform =
            "rotate(" + (rotationOffset + currentAngle).toString() + "deg)";
          // updating percentage
          percentage.innerHTML = Math.round(
            (currentAngle / 360) * 100
          ).toString();
        }
      }
    };
    return Circle;
  })(ElementBase);
  lv.Circle = Circle;
  /**
   * list of linear elements
   */
  var BarType;
  (function (BarType) {
    BarType[(BarType["Line"] = 0)] = "Line";
    BarType[(BarType["BorderedLine"] = 1)] = "BorderedLine";
    BarType[(BarType["DeterminateLine"] = 2)] = "DeterminateLine";
    BarType[(BarType["DeterminateBorderedLine"] = 3)] =
      "DeterminateBorderedLine";
  })((BarType = lv.BarType || (lv.BarType = {})));
  /**
   * list of non-linear elements
   */
  var CircleType;
  (function (CircleType) {
    CircleType[(CircleType["Bars"] = 0)] = "Bars";
    CircleType[(CircleType["Squares"] = 1)] = "Squares";
    CircleType[(CircleType["Circles"] = 2)] = "Circles";
    CircleType[(CircleType["Dots"] = 3)] = "Dots";
    CircleType[(CircleType["DeterminateCircle"] = 4)] = "DeterminateCircle";
    CircleType[(CircleType["Spinner"] = 5)] = "Spinner";
    CircleType[(CircleType["Dashed"] = 6)] = "Dashed";
  })((CircleType = lv.CircleType || (lv.CircleType = {})));
})(lv || (lv = {}));

export { lv };

//# sourceMappingURL=main.js.map
