/* COPYRIGHT Esri - https://js.arcgis.com/1.2/LICENSE.txt */
import { c as customElement } from "../../chunks/runtime.js";
import { P as PopupUtils } from "../../chunks/popupUtils.js";
import { g as getLayerOrTable, c as getFeatureLayerView, h as highlightFeatures } from "../../chunks/mapViewUtils.js";
import { u as useT9n } from "../../chunks/useT9n.js";
import { css, html, nothing } from "lit";
import { createRef, ref } from "lit-html/directives/ref.js";
import { LitElement, createEvent, noShadowRoot, safeClassMap, safeStyleMap } from "@arcgis/lumina";
import config from "@arcgis/core/config";
import * as symbolUtils from "@arcgis/core/symbols/support/symbolUtils";
import * as reactiveUtils from "@arcgis/core/core/reactiveUtils";
const styles = css`@layer{
/** @license
 * Copyright 2025 Esri
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

:host {
  display: block;
}

.width-full {
  width: 100%;
}

.pagination {
  display: flex;
  justify-content: center;
}

.notice-msg {
  padding: 10px;
  width: calc(100% - 20px);
}

.feature-list-popup-title {
  font-weight: 500;
}

.feature-list-popup-title-small {
  font-size: small;
}

.feature-list-popup-title-small-ellipsis {
  font-size: small;
  white-space: nowrap !important;
  text-overflow: ellipsis;
  overflow: hidden;
}

.popup-title {
  padding: 0 5px;
  word-break: break-word;
}

.profile-img {
  margin: 0 5px;
  min-width: 32px;
}

.like-container {
  display: flex;
  align-items: center;
  gap: 5px;
  color: gray !important;
  font-style: italic;
}

.feature-symbol {
  padding: 0 3px;
  min-width: 30px;
  display: flex;
  justify-content: center;
}

.search {
  padding: 10px;
  background-color: var(--calcite-color-foreground-1) !important;
  border-block-end: 1px solid var(--calcite-color-border-3);
}
}`;
class FeatureList extends LitElement {
  constructor() {
    super();
    this.selectedLayerId = "";
    this.noFeaturesFoundMsg = "";
    this.pageSize = 100;
    this.highlightOnMap = false;
    this.highlightOnHover = false;
    this.textSize = "large";
    this.showInitialLoading = true;
    this.showErrorWhenNoFeatures = false;
    this.showUserImageInList = false;
    this.showFeatureSymbol = false;
    this.applyLayerViewFilter = false;
    this.showFullTitle = true;
    this.filterByMapExtent = false;
    this._featureItems = [];
    this._featuresCount = 0;
    this._isLoading = false;
    this._searchPlaceHolder = "";
    this._fullTextSearchInfo = [];
    this._translations = useT9n({ name: "feature-list", blocking: true });
    this._pagination = createRef();
    this._calciteList = createRef();
    this._validFieldTypes = ["small-integer", "integer", "big-integer", "single", "long"];
    this._abbreviatedLikeCount = "";
    this._likeFieldAvailable = false;
    this._searchExpression = "";
    this.featureClick = createEvent();
    this.featureSelect = createEvent();
    this.listenOn(window, "selectedLanguageUpdated", this.selectedLanguageUpdated);
  }
  static {
    this.properties = { selectedLayerId: 1, mapView: [0, {}, { attribute: false }], noFeaturesFoundMsg: 1, pageSize: [9, {}, { type: Number }], highlightOnMap: [5, {}, { type: Boolean }], highlightOnHover: [5, {}, { type: Boolean }], sortingInfo: [0, {}, { attribute: false }], whereClause: 1, textSize: 1, showInitialLoading: [5, {}, { type: Boolean }], showErrorWhenNoFeatures: [5, {}, { type: Boolean }], showUserImageInList: [5, {}, { type: Boolean }], showFeatureSymbol: [5, {}, { type: Boolean }], applyLayerViewFilter: [5, {}, { type: Boolean }], reportingOptions: [0, {}, { attribute: false }], showFullTitle: [5, {}, { type: Boolean }], filterByMapExtent: [5, {}, { type: Boolean }], _featureItems: [16, {}, { state: true }], _featuresCount: [16, {}, { state: true }], _isLoading: [16, {}, { state: true }], _searchPlaceHolder: [16, {}, { state: true }], _fullTextSearchInfo: [16, {}, { state: true }], _translations: [16, {}, { state: true }] };
  }
  static {
    this.styles = styles;
  }
  static {
    this.shadowRootOptions = noShadowRoot;
  }
  willUpdate(changes) {
    if (changes.has("selectedLayerId")) {
      void this.selectedLayerWatchHandler();
    }
    if (changes.has("sortingInfo")) {
      void this.sortingInfoWatchHandler();
    }
    if (changes.has("whereClause")) {
      void this.whereClauseHandler();
    }
    if (changes.has("filterByMapExtent") && this.hasUpdated) {
      void this.filterByMapExtentWatchHandler(this.filterByMapExtent);
    }
  }
  async selectedLayerWatchHandler() {
    this._selectedLayer = this.mapView && await getLayerOrTable(this.mapView, this.selectedLayerId);
    await this.initializeFeatureItems();
  }
  async sortingInfoWatchHandler() {
    await this.initializeFeatureItems();
  }
  async whereClauseHandler() {
    await this.initializeFeatureItems();
  }
  async filterByMapExtentWatchHandler(enabled) {
    if (enabled) {
      this.initializeMapExtentFilter();
    } else if (this._filterByMapExtentHandle) {
      this._filterByMapExtentHandle.remove();
    }
  }
  async refresh(maintainPageState) {
    if (maintainPageState && this._pagination.value) {
      const event = {
        target: {
          startItem: this._pagination.value.startItem
        }
      };
      await this.pageChanged(event);
    } else if (this._searchExpression) {
      await this._searchFullText();
    } else {
      await this.initializeFeatureItems();
    }
  }
  async selectedLanguageUpdated(_evt) {
    if (this._pagination.value) {
      const event = {
        target: {
          startItem: this._pagination.value.startItem
        }
      };
      await this.pageChanged(event);
    } else {
      await this.initializeFeatureItems();
    }
  }
  async load() {
    this._isLoading = this.showInitialLoading ? true : false;
    this._popupUtils = new PopupUtils();
    if (this.mapView && this.selectedLayerId) {
      this._selectedLayer = await getLayerOrTable(this.mapView, this.selectedLayerId);
      this._getFullTextSearchInfo();
    }
    if (this.filterByMapExtent) {
      this.initializeMapExtentFilter();
    }
  }
  async loaded() {
    await this.initializeFeatureItems();
  }
  render() {
    const showSearch = this._canShowFullTextSearch();
    return html`<calcite-panel>${showSearch && html`<calcite-input class=search clearable icon=search @calciteInputChange=${this._searchTextChanged} .placeholder=${this._searchPlaceHolder} title type=search></calcite-input>` || ""}${this._isLoading && html`<calcite-loader label scale=m></calcite-loader>` || ""}${this.showErrorWhenNoFeatures && this._featureItems.length === 0 && !this._isLoading && html`<calcite-notice class="notice-msg" icon=feature-details kind=info open><div slot=message>${this.filterByMapExtent ? this._translations.featureErrorMsgInCurrentMapView : this.noFeaturesFoundMsg ? this.noFeaturesFoundMsg : this._translations.featureErrorMsg}</div></calcite-notice>` || ""}<calcite-list class=${safeClassMap(this.textSize === "small" && !this.showFullTitle ? "overflow-hidden" : "")} label selection-appearance=border selection-mode=none ${ref(this._calciteList)}>${!this._isLoading && this._featureItems.length > 0 && html`<div>${this.filterByMapExtent && this.getExtentNotice() || ""}${this._featureItems}</div>` || ""}</calcite-list>${this.pageSize && this._featuresCount > this.pageSize && html`<div class="width-full" slot=footer><calcite-pagination class="pagination" @calcitePaginationChange=${this.pageChanged} .pageSize=${this.pageSize} start-item=1 .totalItems=${this._featuresCount} ${ref(this._pagination)}></calcite-pagination></div>` || ""}</calcite-panel>`;
  }
  async getWhereCondition() {
    let whereClause = "1=1";
    if (this.whereClause) {
      whereClause = this.whereClause;
    }
    if (this._selectedLayer?.definitionExpression) {
      whereClause = whereClause + " AND " + this._selectedLayer.definitionExpression;
    }
    if (this.applyLayerViewFilter) {
      const selectedLayerView = this.mapView && await getFeatureLayerView(this.mapView, this.selectedLayerId);
      if (selectedLayerView?.filter?.where) {
        whereClause = whereClause + " AND " + selectedLayerView.filter.where;
      }
    }
    return whereClause;
  }
  async initializeFeatureItems() {
    if (this._selectedLayer) {
      void this._pagination.value?.goTo("start");
      this._isLoading = this.showInitialLoading ? true : false;
      this._featureItems = await this.queryPage(0);
      const whereCondition = await this.getWhereCondition();
      const query = {
        where: whereCondition,
        geometry: this.filterByMapExtent ? this.mapView?.extent : null
      };
      this._featuresCount = await this._selectedLayer.queryFeatureCount(query);
      this._isLoading = false;
    }
  }
  initializeMapExtentFilter() {
    this._filterByMapExtentHandle = reactiveUtils.when(() => this.mapView?.stationary, () => {
      void this.initializeFeatureItems();
    }, {
      initial: true
    });
  }
  async pageChanged(event) {
    this._isLoading = true;
    if (this._highlightHandle) {
      this._highlightHandle.remove();
      this._highlightHandle = void 0;
    }
    const page = event.target.startItem - 1;
    this._featureItems = await this.queryPage(page);
    this._isLoading = false;
  }
  _canShowFullTextSearch() {
    return this._selectedLayer?.capabilities?.query?.supportsFullTextSearch && this._selectedLayer.indexes.items.filter((i) => i.indexType == "FullText").length > 0;
  }
  _getFullTextSearchInfo() {
    this._fullTextSearchInfo = [];
    if (this._selectedLayer?.capabilities?.query?.supportsFullTextSearch) {
      const fullTextIndexes = this._selectedLayer.indexes?.filter((i) => i.indexType == "FullText");
      if (fullTextIndexes?.length) {
        const onFields = [];
        fullTextIndexes.forEach((index) => {
          onFields.push(...index.fields.split(","));
        });
        const fieldAlias = [];
        onFields.forEach((fieldName) => {
          const fieldInfo = this._selectedLayer?.getField(fieldName.trim());
          fieldAlias.push(fieldInfo?.alias || "");
        });
        this._searchPlaceHolder = this._translations.searchPlaceholder ? this._translations.searchPlaceholder.replace("{{field_names}}", fieldAlias.join(", ")) : "";
        this._fullTextSearchInfo.push({
          onFields: ["*"],
          searchTerm: "",
          searchType: "prefix"
        });
      }
    }
  }
  async _searchTextChanged(event) {
    this._fullTextSearchInfo.forEach((searchInfo) => {
      searchInfo.searchTerm = event.target.value;
    });
    await this._searchFullText();
  }
  async _searchFullText() {
    if (this._searchExpression) {
      this._clearSearchDefinitionExpression();
    }
    let searchedIds = [];
    if (this._fullTextSearchInfo) {
      if (this._fullTextSearchInfo[0].searchTerm) {
        const searchQueryParams = this._selectedLayer?.createQuery();
        if (searchQueryParams) {
          searchQueryParams.fullText = this._fullTextSearchInfo;
          searchedIds = await this._selectedLayer?.queryObjectIds(searchQueryParams);
          await this._updateSearchDefinitionExpression(searchedIds?.length ? searchedIds : [-1]);
        }
      }
    }
    await this.initializeFeatureItems();
  }
  async _updateSearchDefinitionExpression(searchedIds) {
    if (this._selectedLayer) {
      const defExp = this._selectedLayer.definitionExpression;
      if (searchedIds?.length) {
        const searchExp = `objectId in(${searchedIds})`;
        this._selectedLayer.definitionExpression = this._searchExpression && defExp && defExp?.indexOf(this._searchExpression) > -1 ? defExp.replace(this._searchExpression, searchExp) : defExp ? `${defExp} AND (${searchExp})` : searchExp;
        this._searchExpression = searchExp;
      } else {
        this._clearSearchDefinitionExpression();
      }
    }
  }
  _clearSearchDefinitionExpression() {
    if (this._selectedLayer) {
      const defExp = this._selectedLayer?.definitionExpression;
      if (this._searchExpression && defExp && defExp?.indexOf(this._searchExpression) > -1) {
        if (defExp?.indexOf(" AND (" + this._searchExpression) > -1) {
          this._selectedLayer.definitionExpression = defExp.replace(` AND (${this._searchExpression})`, "");
        } else {
          this._selectedLayer.definitionExpression = defExp.replace(this._searchExpression, "");
        }
      }
    }
    this._searchExpression = "";
  }
  async featureClicked(event, selectedFeature) {
    this.featureClick.emit();
    this.clearHighlights();
    if (this.highlightOnMap) {
      const selectedFeatureObjectId = Number(event.target.value);
      const selectedLayerView = this.mapView && await getFeatureLayerView(this.mapView, this.selectedLayerId);
      this._highlightHandle = selectedLayerView && this.mapView ? await highlightFeatures([selectedFeatureObjectId], selectedLayerView, this.mapView, true) : void 0;
    }
    await this.emitSelectedFeature(selectedFeature);
  }
  async emitSelectedFeature(graphic) {
    const layer = graphic.layer;
    const query = layer.createQuery();
    query.returnGeometry = true;
    const id = Number(graphic.getObjectId());
    if (!Number.isNaN(id) && query) {
      query.objectIds = [id];
      const completeGraphic = await layer.queryFeatures(query);
      this.featureSelect.emit(completeGraphic.features[0]);
    }
  }
  async onFeatureHover(selectedFeature) {
    this.clearHighlights();
    if (this.highlightOnHover) {
      const oId = Number(selectedFeature.getObjectId());
      const selectedLayerView = this.mapView && await getFeatureLayerView(this.mapView, this.selectedLayerId);
      if (selectedLayerView) {
        this._highlightHandle = selectedLayerView.highlight([oId], { name: "temporary" });
      }
    }
  }
  clearHighlights() {
    if (this._highlightHandle) {
      this._highlightHandle.remove();
    }
  }
  async queryPage(page) {
    const featureLayer = this._selectedLayer;
    if (featureLayer) {
      const sortField = this.sortingInfo?.field ? this.sortingInfo.field : featureLayer.objectIdField;
      const sortOrder = this.sortingInfo?.order ? this.sortingInfo.order : "desc";
      const whereCondition = await this.getWhereCondition();
      const query = {
        start: page,
        num: this.pageSize,
        outFields: ["*"],
        returnGeometry: true,
        where: whereCondition,
        outSpatialReference: this.mapView?.spatialReference.toJSON(),
        geometry: this.filterByMapExtent ? this.mapView?.extent : null
      };
      if (sortField && sortOrder) {
        query.orderByFields = [sortField.toString() + " " + sortOrder];
      }
      const featureSet = await featureLayer.queryFeatures(query);
      return await this.createFeatureItem(featureSet);
    } else {
      return void 0;
    }
  }
  async createFeatureItem(featureSet) {
    const currentFeatures = featureSet?.features;
    const showLikeCount = this.reportingOptions && this.reportingOptions[this.selectedLayerId].like;
    const items = currentFeatures.map(async (feature) => {
      const popupTitle = this.mapView?.map && await this._popupUtils?.getPopupTitle(feature, this.mapView.map) || "";
      let userInfo;
      let featureSymbol;
      if (this.showUserImageInList) {
        const creatorField = this._selectedLayer?.editFieldsInfo?.creatorField;
        if (creatorField) {
          userInfo = await this.getUserInformation(feature);
        }
      }
      if (this.showFeatureSymbol) {
        featureSymbol = await this.getFeatureSymbol(feature);
      }
      if (showLikeCount) {
        void this.getAbbreviatedLikeCount(feature);
      }
      return this.getFeatureItem(feature, popupTitle, featureSymbol, userInfo);
    });
    return Promise.all(items);
  }
  getExtentNotice() {
    return html`<calcite-notice class="notice-msg" icon=extent-filter kind=brand open scale=s><div slot=message>${this._translations.extentFilterMsg}</div></calcite-notice>`;
  }
  getAbbreviatedLikeCount(feature) {
    const selectedLayer = this._selectedLayer;
    if (selectedLayer) {
      const likeField = this.reportingOptions && this.reportingOptions[selectedLayer.id].likeField;
      selectedLayer.fields.forEach((eachField) => {
        if (this._validFieldTypes.indexOf(eachField.type) > -1) {
          if (eachField.name === likeField && this.reportingOptions && this.reportingOptions[selectedLayer.id].like) {
            this._likeFieldAvailable = true;
            let likes = feature.attributes[likeField] || 0;
            if (likes > 999 && this._translations.millions_value && this._translations.thousands_value) {
              likes = likes > 999999 ? this._translations.millions_value.replace("{{millions_value}}", Math.floor(likes / 1e6).toString()) : this._translations.thousands_value.replace("{{thousands_value}}", Math.floor(likes / 1e3).toString());
            }
            this._abbreviatedLikeCount = likes;
          }
        }
      });
    }
  }
  getFeatureItem(selectedFeature, popupTitle, featureSymbol, userInfo) {
    if (this._selectedLayer?.id && this._calciteList.value) {
      const oId = selectedFeature.attributes[this._selectedLayer.objectIdField].toString();
      popupTitle = popupTitle ?? oId;
      const formattedLikeCount = Number(selectedFeature.attributes[this.reportingOptions?.[this._selectedLayer.id].likeField || ""]).toLocaleString();
      const popupTitleClass = this.textSize === "small" && !this.showFullTitle ? "feature-list-popup-title-small-ellipsis" : this.textSize === "small" ? "feature-list-popup-title-small" : "feature-list-popup-title";
      const deductedWidth = this.showUserImageInList ? 115 : 65;
      const width = this._calciteList.value.offsetWidth - deductedWidth;
      return html`<calcite-list-item @mouseleave=${() => {
        void this.clearHighlights();
      }} @mouseover=${() => {
        void this.onFeatureHover(selectedFeature);
      }} @calciteListItemSelect=${(e) => {
        void this.featureClicked(e, selectedFeature);
      }} .value=${oId}>${this.showUserImageInList && html`<calcite-avatar class=profile-img .fullName=${userInfo?.fullName} scale=m slot=content-start .thumbnail=${userInfo?.userProfileUrl} .userId=${userInfo?.id} .username=${userInfo?.fullName ? userInfo.username : void 0}></calcite-avatar>` || ""}${this.showFeatureSymbol && featureSymbol && html`<div class=feature-symbol slot=content-start ${ref((el) => el && el.replaceChildren(featureSymbol))}></div>` || ""}<div class=${`popup-title ${popupTitleClass}`} slot=content-start style=${safeStyleMap({ maxWidth: this.textSize === "large" ? "none" : `${width}px` })}>${popupTitle}</div>${this._likeFieldAvailable && html`<div class=like-container id=${oId.concat("like") ?? nothing} slot=content-end><span>${this._abbreviatedLikeCount}</span><calcite-icon icon=thumbs-up scale=s></calcite-icon><calcite-tooltip overlay-positioning=fixed placement=top .referenceElement=${oId.concat("like")}>${formattedLikeCount}</calcite-tooltip></div>` || ""}<calcite-icon flip-rtl icon=chevron-right scale=s slot=content-end></calcite-icon></calcite-list-item>`;
    } else {
      return void 0;
    }
  }
  async getUserInformation(feature) {
    let creatorField = this._selectedLayer?.editFieldsInfo?.creatorField;
    if (creatorField) {
      if (feature.attributes.hasOwnProperty(creatorField.toLowerCase())) {
        creatorField = creatorField.toLowerCase();
      } else if (feature.attributes.hasOwnProperty(creatorField.toUpperCase())) {
        creatorField = creatorField.toUpperCase();
      }
      let url = `${config.portalUrl}/sharing/rest/community/users/${feature.attributes[creatorField]}?f=json&returnUserLicensedItems=true`;
      const userToken = this.mapView?.map?.portalItem.portal?.credential?.token;
      if (userToken) {
        url += `&token=${userToken}`;
      }
      const data = await fetch(url);
      const userInfo = await data.json();
      const userName = userInfo?.username ?? feature.attributes[creatorField];
      let userProfileUrl = `${config.portalUrl}/sharing/rest/community/users/${userName}/info/blob.png`;
      if (userInfo?.access && userToken) {
        userProfileUrl += `?token=${userToken}`;
      }
      userInfo.userProfileUrl = userProfileUrl;
      return userInfo;
    } else {
      return void 0;
    }
  }
  async getFeatureSymbol(feature) {
    const nodeHtml = document.createElement("div");
    await symbolUtils?.getDisplayedSymbol(feature).then(async (symbol) => {
      symbol && await symbolUtils?.renderPreviewHTML(symbol, {
        node: nodeHtml
      });
      if (nodeHtml.children?.length) {
        const imgOrSvgElm = nodeHtml.children[0];
        if (imgOrSvgElm) {
          const height = Number(imgOrSvgElm.getAttribute("height"));
          const width = Number(imgOrSvgElm.getAttribute("width"));
          if (width > 30) {
            nodeHtml.setAttribute("width", "30");
            imgOrSvgElm.setAttribute("width", "30");
          }
          if (height > 30) {
            nodeHtml.setAttribute("height", "30");
            imgOrSvgElm.setAttribute("height", "30");
          }
          imgOrSvgElm.setAttribute("viewBox", `0 0 ${width} ${height}`);
          nodeHtml.setAttribute("viewBox", `0 0 ${width} ${height}`);
        }
      }
    });
    return nodeHtml;
  }
}
customElement("feature-list", FeatureList);
export {
  FeatureList
};
