import { h, } from "@stencil/core";
import { _t } from "../i18n/i18n";
let _nextId = 0;
export class Table {
  constructor() {
    this.columns = [];
    this.disableDefaultSort = false;
    this.features = [];
    this.rowClassAttribute = undefined;
    this.sortAttribute = undefined;
    this.sortOrder = "asc";
  }
  componentWillLoad() {
    if (this.el.id == undefined) {
      this.el.id = "table-" + _nextId.toString();
      _nextId += 1;
    }
    this.updateColumns();
  }
  updateColumns() {
    this.columns = Array.from(this.el.querySelectorAll("gl-table-column"));
  }
  setSort(column) {
    if (column.attribute === this.sortAttribute) {
      this.sortOrder = this.sortOrder === "asc" ? "desc" : "asc";
    }
    else {
      this.sortAttribute = column.attribute;
      this.sortOrder = "asc";
    }
    this.glTableSort.emit({
      tableId: this.el.id,
      attribute: this.sortAttribute,
      order: this.sortOrder,
    });
  }
  /**
   * Returns the features the table displays in sorted order
   * @returns
   */
  async getSortedFeatures() {
    return this.sortedFeatures();
  }
  sortedFeatures() {
    if (this.disableDefaultSort)
      return this.features;
    let features = [...this.features];
    features.sort((aFeature, bFeature) => {
      let a = aFeature.properties[this.sortAttribute];
      let b = bFeature.properties[this.sortAttribute];
      if (typeof a === "string")
        a = a.toUpperCase();
      if (typeof b === "string")
        b = b.toUpperCase();
      let cmp = 0;
      if (a > b)
        cmp = 1;
      else if (a < b)
        cmp = -1;
      return this.sortOrder === "desc" ? cmp * -1 : cmp;
    });
    return features;
  }
  renderHeader(column) {
    let columnProps = {};
    if (column.sortable) {
      columnProps = {
        class: "sortable sorted-none",
        tabindex: 0,
        "aria-controls": this.el.id,
        "aria-label": `${column.label}: ` + _t(`webmapgl.table.header.sort-action.desc`),
        onClick: () => this.setSort(column),
      };
      if (column.attribute === this.sortAttribute) {
        columnProps["class"] = `sortable sorted-${this.sortOrder}`;
        columnProps["aria-sort"] =
          this.sortOrder === "asc" ? "ascending" : "descending";
        columnProps["aria-label"] =
          `${column.label}: ` +
            _t(`webmapgl.table.header.sort-action.${this.sortOrder}`);
      }
    }
    return h("th", Object.assign({}, columnProps), column.label);
  }
  /**
   * Returns the contents of a cell
   * @param feature
   * @param column
   * @param format
   * @returns
   */
  async getCellContents(feature, column, format) {
    let value = feature.properties[column.attribute];
    if (column.component == undefined)
      return this.renderValue(column, value);
    return await this.renderComponentAsText(feature, column, value, format);
  }
  renderValue(column, value) {
    if (value == undefined)
      return null;
    if (column.format)
      value = value.toLocaleString({}, column.format);
    return value.toString();
  }
  renderComponentJSX(feature, column, value) {
    let Component = column.component;
    let props = column.componentProps || {};
    return (h(Component, Object.assign({ feature: feature, column: column, value: value }, props)));
  }
  async renderComponentAsText(feature, column, value, format) {
    let component = document.createElement(column.component);
    let props = column.componentProps || {};
    for (let prop in props)
      component[prop] = props[prop];
    component.feature = feature;
    component.column = column;
    component.value = value;
    component.style.display = "none";
    this.el.appendChild(component);
    await component.componentOnReady();
    let result = typeof component.formatValue === "function"
      ? component.formatValue(format)
      : component.textContent;
    this.el.removeChild(component);
    return result;
  }
  renderCell(feature, column) {
    let value = feature.properties[column.attribute];
    let cssClass = column.cellClassAttribute != undefined
      ? feature.properties[column.cellClassAttribute]
      : "cell";
    return (h("td", { class: cssClass }, column.component != undefined
      ? this.renderComponentJSX(feature, column, value)
      : this.renderValue(column, value)));
  }
  renderRow(feature, columns) {
    let cssClass = this.rowClassAttribute != undefined
      ? feature.properties[this.rowClassAttribute]
      : "row";
    return (h("tr", { class: cssClass }, columns.map((col) => this.renderCell(feature, col))));
  }
  render() {
    if (this.columns.length === 0)
      return null;
    let features = this.sortedFeatures();
    let columns = this.columns.filter((col) => col.visible);
    let header = columns.map((col) => this.renderHeader(col));
    let bodyRows = features.map((feature) => this.renderRow(feature, columns));
    return (h("table", { id: this.el.id }, h("thead", null, h("tr", null, header)), h("tbody", null, bodyRows)));
  }
  static get is() { return "gl-table"; }
  static get originalStyleUrls() {
    return {
      "$": ["table.css"]
    };
  }
  static get styleUrls() {
    return {
      "$": ["table.css"]
    };
  }
  static get properties() {
    return {
      "disableDefaultSort": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Whether or not to disable the default sorting options"
        },
        "attribute": "disable-default-sort",
        "reflect": false,
        "defaultValue": "false"
      },
      "features": {
        "type": "unknown",
        "mutable": true,
        "complexType": {
          "original": "{ properties: { [key: string]: any } }[]",
          "resolved": "{ properties: { [key: string]: any; }; }[]",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "The features this table displays"
        },
        "defaultValue": "[]"
      },
      "rowClassAttribute": {
        "type": "string",
        "mutable": false,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "The name of the attribute whose value to use as the css class of the row."
        },
        "attribute": "row-class-attribute",
        "reflect": false
      },
      "sortAttribute": {
        "type": "string",
        "mutable": true,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "What attribute to sort on"
        },
        "attribute": "sort-attribute",
        "reflect": false
      },
      "sortOrder": {
        "type": "string",
        "mutable": true,
        "complexType": {
          "original": "\"asc\" | \"desc\"",
          "resolved": "\"asc\" | \"desc\"",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "What order to use for sorting"
        },
        "attribute": "sort-order",
        "reflect": false,
        "defaultValue": "\"asc\""
      }
    };
  }
  static get states() {
    return {
      "columns": {}
    };
  }
  static get events() {
    return [{
        "method": "glTableSort",
        "name": "glTableSort",
        "bubbles": true,
        "cancelable": true,
        "composed": true,
        "docs": {
          "tags": [],
          "text": "Event emitted when the table sort order is changed"
        },
        "complexType": {
          "original": "any",
          "resolved": "any",
          "references": {}
        }
      }];
  }
  static get methods() {
    return {
      "getSortedFeatures": {
        "complexType": {
          "signature": "() => Promise<{ properties: { [key: string]: any; }; }[]>",
          "parameters": [],
          "references": {
            "Promise": {
              "location": "global",
              "id": "global::Promise"
            }
          },
          "return": "Promise<{ properties: { [key: string]: any; }; }[]>"
        },
        "docs": {
          "text": "Returns the features the table displays in sorted order",
          "tags": [{
              "name": "returns",
              "text": undefined
            }]
        }
      },
      "getCellContents": {
        "complexType": {
          "signature": "(feature: { properties: { [key: string]: any; }; }, column: HTMLGlTableColumnElement, format: \"pdf\" | \"text\") => Promise<any>",
          "parameters": [{
              "tags": [{
                  "name": "param",
                  "text": "feature"
                }],
              "text": ""
            }, {
              "tags": [{
                  "name": "param",
                  "text": "column"
                }],
              "text": ""
            }, {
              "tags": [{
                  "name": "param",
                  "text": "format"
                }],
              "text": ""
            }],
          "references": {
            "Promise": {
              "location": "global",
              "id": "global::Promise"
            },
            "HTMLGlTableColumnElement": {
              "location": "global",
              "id": "global::HTMLGlTableColumnElement"
            }
          },
          "return": "Promise<any>"
        },
        "docs": {
          "text": "Returns the contents of a cell",
          "tags": [{
              "name": "param",
              "text": "feature"
            }, {
              "name": "param",
              "text": "column"
            }, {
              "name": "param",
              "text": "format"
            }, {
              "name": "returns",
              "text": undefined
            }]
        }
      }
    };
  }
  static get elementRef() { return "el"; }
  static get listeners() {
    return [{
        "name": "glTableColumnChanged",
        "method": "updateColumns",
        "target": undefined,
        "capture": false,
        "passive": false
      }];
  }
}
//# sourceMappingURL=table.js.map
