"use strict";

require("core-js/modules/es.symbol.iterator.js");
require("core-js/modules/es.array.iterator.js");
require("core-js/modules/es.string.iterator.js");
require("core-js/modules/web.dom-collections.iterator.js");
exports.__esModule = true;
exports.default = void 0;
require("core-js/modules/es.symbol.to-primitive.js");
require("core-js/modules/es.date.to-primitive.js");
require("core-js/modules/es.symbol.js");
require("core-js/modules/es.symbol.description.js");
require("core-js/modules/es.object.to-string.js");
require("core-js/modules/es.number.constructor.js");
var _element = require("../../../../helpers/dom/element");
var _string = require("../../../../helpers/string");
var _eventManager = _interopRequireDefault(require("../../../../eventManager"));
var _scroll = _interopRequireDefault(require("../scroll"));
var _coords = _interopRequireDefault(require("../cell/coords"));
var _range = _interopRequireDefault(require("../cell/range"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
/**
 * @abstract
 * @class Walkontable
 */
var CoreAbstract = /*#__PURE__*/function () {
  /**
   * @param {HTMLTableElement} table Main table.
   * @param {Settings} settings The Walkontable settings.
   */
  function CoreAbstract(table, settings) {
    _classCallCheck(this, CoreAbstract);
    _defineProperty(this, "wtTable", void 0);
    _defineProperty(this, "wtScroll", void 0);
    _defineProperty(this, "wtViewport", void 0);
    _defineProperty(this, "wtOverlays", void 0);
    _defineProperty(this, "selectionManager", void 0);
    _defineProperty(this, "wtEvent", void 0);
    /**
     * The walkontable instance id.
     *
     * @public
     * @type {Readonly<string>}
     */
    _defineProperty(this, "guid", "wt_".concat((0, _string.randomString)()));
    _defineProperty(this, "drawInterrupted", false);
    _defineProperty(this, "drawn", false);
    /**
     * The DOM bindings.
     *
     * @public
     * @type {DomBindings}
     */
    _defineProperty(this, "domBindings", void 0);
    /**
     * Settings.
     *
     * @public
     * @type {Settings}
     */
    _defineProperty(this, "wtSettings", void 0);
    this.domBindings = {
      rootTable: table,
      rootDocument: table.ownerDocument,
      rootWindow: table.ownerDocument.defaultView
    };
    this.wtSettings = settings;
    this.wtScroll = new _scroll.default(this.createScrollDao());
  }
  _createClass(CoreAbstract, [{
    key: "eventManager",
    get: function get() {
      return new _eventManager.default(this);
    }
  }, {
    key: "findOriginalHeaders",
    value: function findOriginalHeaders() {
      var originalHeaders = [];

      // find original headers
      if (this.wtTable.THEAD.childNodes.length && this.wtTable.THEAD.childNodes[0].childNodes.length) {
        for (var c = 0, clen = this.wtTable.THEAD.childNodes[0].childNodes.length; c < clen; c++) {
          originalHeaders.push(this.wtTable.THEAD.childNodes[0].childNodes[c].innerHTML);
        }
        if (!this.wtSettings.getSetting('columnHeaders').length) {
          this.wtSettings.update('columnHeaders', [function (column, TH) {
            (0, _element.fastInnerText)(TH, originalHeaders[column]);
          }]);
        }
      }
    }

    /**
     * Creates and returns the CellCoords object.
     *
     * @param {*} row The row index.
     * @param {*} column The column index.
     * @returns {CellCoords}
     */
  }, {
    key: "createCellCoords",
    value: function createCellCoords(row, column) {
      return new _coords.default(row, column, this.wtSettings.getSetting('rtlMode'));
    }

    /**
     * Creates and returns the CellRange object.
     *
     * @param {CellCoords} highlight The highlight coordinates.
     * @param {CellCoords} from The from coordinates.
     * @param {CellCoords} to The to coordinates.
     * @returns {CellRange}
     */
  }, {
    key: "createCellRange",
    value: function createCellRange(highlight, from, to) {
      return new _range.default(highlight, from, to, this.wtSettings.getSetting('rtlMode'));
    }

    /**
     * Force rerender of Walkontable.
     *
     * @param {boolean} [fastDraw=false] When `true`, try to refresh only the positions of borders without rerendering
     *                                   the data. It will only work if Table.draw() does not force
     *                                   rendering anyway.
     * @returns {Walkontable}
     */
  }, {
    key: "draw",
    value: function draw() {
      var fastDraw = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
      this.drawInterrupted = false;
      if (!fastDraw && !this.wtTable.isVisible()) {
        // draw interrupted because TABLE is not visible
        this.drawInterrupted = true;
      } else {
        this.wtTable.draw(fastDraw);
      }
      return this;
    }

    /**
     * Returns the TD at coords. If topmost is set to true, returns TD from the topmost overlay layer,
     * if not set or set to false, returns TD from the master table.
     *
     * @param {CellCoords} coords The cell coordinates.
     * @param {boolean} [topmost=false] If set to `true`, it returns the TD element from the topmost overlay. For example,
     *                                  if the wanted cell is in the range of fixed rows, it will return a TD element
     *                                  from the top overlay.
     * @returns {HTMLElement}
     */
  }, {
    key: "getCell",
    value: function getCell(coords) {
      var topmost = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
      if (!topmost) {
        return this.wtTable.getCell(coords);
      }
      var totalRows = this.wtSettings.getSetting('totalRows');
      var fixedRowsTop = this.wtSettings.getSetting('fixedRowsTop');
      var fixedRowsBottom = this.wtSettings.getSetting('fixedRowsBottom');
      var fixedColumnsStart = this.wtSettings.getSetting('fixedColumnsStart');
      if (coords.row < fixedRowsTop && coords.col < fixedColumnsStart) {
        return this.wtOverlays.topInlineStartCornerOverlay.clone.wtTable.getCell(coords);
      } else if (coords.row < fixedRowsTop) {
        return this.wtOverlays.topOverlay.clone.wtTable.getCell(coords);
      } else if (coords.col < fixedColumnsStart && coords.row >= totalRows - fixedRowsBottom) {
        if (this.wtOverlays.bottomInlineStartCornerOverlay && this.wtOverlays.bottomInlineStartCornerOverlay.clone) {
          return this.wtOverlays.bottomInlineStartCornerOverlay.clone.wtTable.getCell(coords);
        }
      } else if (coords.col < fixedColumnsStart) {
        return this.wtOverlays.inlineStartOverlay.clone.wtTable.getCell(coords);
      } else if (coords.row < totalRows && coords.row >= totalRows - fixedRowsBottom) {
        if (this.wtOverlays.bottomOverlay && this.wtOverlays.bottomOverlay.clone) {
          return this.wtOverlays.bottomOverlay.clone.wtTable.getCell(coords);
        }
      }
      return this.wtTable.getCell(coords);
    }

    /**
     * Scrolls the viewport to a cell (rerenders if needed).
     *
     * @param {CellCoords} coords The cell coordinates to scroll to.
     * @param {boolean} [snapToTop] If `true`, viewport is scrolled to show the cell on the top of the table.
     * @param {boolean} [snapToRight] If `true`, viewport is scrolled to show the cell on the right of the table.
     * @param {boolean} [snapToBottom] If `true`, viewport is scrolled to show the cell on the bottom of the table.
     * @param {boolean} [snapToLeft] If `true`, viewport is scrolled to show the cell on the left of the table.
     * @returns {boolean}
     */
  }, {
    key: "scrollViewport",
    value: function scrollViewport(coords, snapToTop, snapToRight, snapToBottom, snapToLeft) {
      if (coords.col < 0 || coords.row < 0) {
        return false;
      }
      return this.wtScroll.scrollViewport(coords, snapToTop, snapToRight, snapToBottom, snapToLeft);
    }

    /**
     * Scrolls the viewport to a column (rerenders if needed).
     *
     * @param {number} column Visual column index.
     * @param {boolean} [snapToRight] If `true`, viewport is scrolled to show the cell on the right of the table.
     * @param {boolean} [snapToLeft] If `true`, viewport is scrolled to show the cell on the left of the table.
     * @returns {boolean}
     */
  }, {
    key: "scrollViewportHorizontally",
    value: function scrollViewportHorizontally(column, snapToRight, snapToLeft) {
      if (column < 0) {
        return false;
      }
      return this.wtScroll.scrollViewportHorizontally(column, snapToRight, snapToLeft);
    }

    /**
     * Scrolls the viewport to a row (rerenders if needed).
     *
     * @param {number} row Visual row index.
     * @param {boolean} [snapToTop] If `true`, viewport is scrolled to show the cell on the top of the table.
     * @param {boolean} [snapToBottom] If `true`, viewport is scrolled to show the cell on the bottom of the table.
     * @returns {boolean}
     */
  }, {
    key: "scrollViewportVertically",
    value: function scrollViewportVertically(row, snapToTop, snapToBottom) {
      if (row < 0) {
        return false;
      }
      return this.wtScroll.scrollViewportVertically(row, snapToTop, snapToBottom);
    }

    /**
     * @returns {Array}
     */
  }, {
    key: "getViewport",
    value: function getViewport() {
      return [this.wtTable.getFirstVisibleRow(), this.wtTable.getFirstVisibleColumn(), this.wtTable.getLastVisibleRow(), this.wtTable.getLastVisibleColumn()];
    }

    /**
     * Destroy instance.
     */
  }, {
    key: "destroy",
    value: function destroy() {
      this.wtOverlays.destroy();
      this.wtEvent.destroy();
    }

    /**
     * Create data access object for scroll.
     *
     * @protected
     * @returns {ScrollDao}
     */
  }, {
    key: "createScrollDao",
    value: function createScrollDao() {
      var wot = this;
      return {
        get drawn() {
          return wot.drawn; // TODO refactoring: consider about injecting `isDrawn` function : ()=>return wot.drawn. (it'll enables remove dao layer)
        },

        get topOverlay() {
          return wot.wtOverlays.topOverlay; // TODO refactoring: move outside dao, use IOC
        },

        get inlineStartOverlay() {
          return wot.wtOverlays.inlineStartOverlay; // TODO refactoring: move outside dao, use IOC
        },

        get wtTable() {
          return wot.wtTable; // TODO refactoring: move outside dao, use IOC
        },

        get wtViewport() {
          return wot.wtViewport; // TODO refactoring: move outside dao, use IOC
        },

        get wtSettings() {
          return wot.wtSettings;
        },
        get rootWindow() {
          return wot.domBindings.rootWindow; // TODO refactoring: move outside dao
        },

        // TODO refactoring, consider about using injecting wtSettings into scroll (it'll enables remove dao layer)
        get totalRows() {
          return wot.wtSettings.getSetting('totalRows');
        },
        get totalColumns() {
          return wot.wtSettings.getSetting('totalColumns');
        },
        get fixedRowsTop() {
          return wot.wtSettings.getSetting('fixedRowsTop');
        },
        get fixedRowsBottom() {
          return wot.wtSettings.getSetting('fixedRowsBottom');
        },
        get fixedColumnsStart() {
          return wot.wtSettings.getSetting('fixedColumnsStart');
        }
      };
    }
    // TODO refactoring: it will be much better to not use DAO objects. They are needed for now to provide
    // dynamically access to related objects
    /**
     * Create data access object for wtTable.
     *
     * @protected
     * @returns {TableDao}
     */
  }, {
    key: "getTableDao",
    value: function getTableDao() {
      var wot = this;
      return {
        get wot() {
          return wot;
        },
        get parentTableOffset() {
          return wot.cloneSource.wtTable.tableOffset; // TODO rethink: cloneSource exists only in Clone type.
        },

        get cloneSource() {
          return wot.cloneSource; // TODO rethink: cloneSource exists only in Clone type.
        },

        get workspaceWidth() {
          return wot.wtViewport.getWorkspaceWidth();
        },
        get wtViewport() {
          return wot.wtViewport; // TODO refactoring: move outside dao, use IOC
        },

        get wtOverlays() {
          return wot.wtOverlays; // TODO refactoring: move outside dao, use IOC
        },

        get selectionManager() {
          return wot.selectionManager; // TODO refactoring: move outside dao, use IOC
        },

        get drawn() {
          return wot.drawn;
        },
        set drawn(v) {
          // TODO rethink: this breaks assumes of data access object, however it is required until invent better way to handle WOT state.
          wot.drawn = v;
        },
        get wtTable() {
          return wot.wtTable; // TODO refactoring: it provides itself
        },

        get startColumnRendered() {
          return wot.wtViewport.columnsRenderCalculator.startColumn;
        },
        get startColumnVisible() {
          return wot.wtViewport.columnsVisibleCalculator.startColumn;
        },
        get endColumnRendered() {
          return wot.wtViewport.columnsRenderCalculator.endColumn;
        },
        get endColumnVisible() {
          return wot.wtViewport.columnsVisibleCalculator.endColumn;
        },
        get countColumnsRendered() {
          return wot.wtViewport.columnsRenderCalculator.count;
        },
        get countColumnsVisible() {
          return wot.wtViewport.columnsVisibleCalculator.count;
        },
        get startRowRendered() {
          return wot.wtViewport.rowsRenderCalculator.startRow;
        },
        get startRowVisible() {
          return wot.wtViewport.rowsVisibleCalculator.startRow;
        },
        get endRowRendered() {
          return wot.wtViewport.rowsRenderCalculator.endRow;
        },
        get endRowVisible() {
          return wot.wtViewport.rowsVisibleCalculator.endRow;
        },
        get countRowsRendered() {
          return wot.wtViewport.rowsRenderCalculator.count;
        },
        get countRowsVisible() {
          return wot.wtViewport.rowsVisibleCalculator.count;
        },
        get columnHeaders() {
          return wot.wtSettings.getSetting('columnHeaders');
        },
        get rowHeaders() {
          return wot.wtSettings.getSetting('rowHeaders');
        }
      };
    }
  }]);
  return CoreAbstract;
}();
exports.default = CoreAbstract;