/* COPYRIGHT Esri - https://js.arcgis.com/1.2/LICENSE.txt */
import { s as sortCache, d as createFilteredSubcache, e as extractFromCache, b as getDeployedRelatedSolutionIds } from "./cardsHelpers.js";
import * as common from "@esri/solution-common";
import { d as getAnonymousPortalUrl, g as getTypeKeywordProp, e as createDivHtml, f as getLocaleLongDateString, i as generateThumbnailUrl, j as createUrlParams } from "./helpers.js";
import { B as BASE_DEPLOYED_TERMS } from "./interfaces.js";
class CardsFetcher {
  /**
   * Constructor
   *
   * @param orgUrl URL of organization, e.g., "http://myOrg.maps.arcgis.com"
   * @param portalUrl URL of portal, e.g., "https://www.arcgis.com"
   * @param userSession Authentication
   */
  constructor(locale, orgUrl, portalUrl) {
    this.cMissingImageDataURI = "https://static.arcgis.com/images/solution.png";
    this.cardCache = [];
    this.cardCacheParams = {
      q: "",
      categoriesAsStr: "[]",
      sortField: "title",
      sortOrder: "asc"
    };
    this.locale = locale;
    this.orgUrl = orgUrl;
    this.portalUrl = portalUrl;
    this.anonAgolSession = new common.UserSession({});
    this.agolPortalUrl = getAnonymousPortalUrl(portalUrl);
  }
  /**
   * Adds a card to the cache to keep cache fresh between full refreshes.
   *
   * @param card Card to add
   */
  addToCache(card) {
    this.cardCache.push(card);
  }
  /**
   * Returns the current cache.
   *
   * @returns Cards in the cache
   */
  getCache() {
    return this.cardCache;
  }
  /**
   * Removes a card to the cache to keep cache fresh between full refreshes.
   *
   * @param id Id of card to remove
   */
  removeFromCache(id) {
    this.cardCache = this.cardCache.filter((card) => card.id !== id);
  }
  /**
   * Fetches cards for availale Solutions from the server.
   *
   * @param query AGO query terms and options
   * @param primarySolutionsGroupId Id of a group that's the primary source of Solutions for AGO or Enterprise
   * @param agoBasedEnterpriseSolutionsGroupId Id of an AGO-based set of Enterprise Solutions
   * @param userSession Authentication for thumbnailUrl
   * @param pagingParams Parameters for how the request is to be batched
   * @param acceptableIds A set of item ids that the results must be a part of; if not defined, then there's no restriction
   * @returns A promise resolving to a collection of available Solutions as cards as well as paging information about
   * where those cards came from in the fetcher cache; in case of failure, the promise resolves to an error message
   */
  requestAvailableSolutionCards(query, primarySolutionsGroupId, agoBasedEnterpriseSolutionsGroupId, userSession, isEnterprise, pagingParams, acceptableIds) {
    const start1 = pagingParams?.start ? pagingParams.start : 1;
    const num = pagingParams?.num ? pagingParams.num : 24;
    const portalUrl = this.portalUrl + "/sharing/rest";
    const agolPortalUrl = this.agolPortalUrl + "/sharing/rest";
    const anonAgolSession = this.anonAgolSession;
    const categoriesAsStr = JSON.stringify(query.categories);
    if (this.cardCacheParams.q !== query.q || this.cardCacheParams.categoriesAsStr !== categoriesAsStr || query.sortField === "relevance") {
      this.cardCache = [];
      this.cardCacheParams = {
        q: query.q,
        categoriesAsStr,
        sortField: query.sortField,
        sortOrder: query.sortOrder
      };
    } else if (this.cardCacheParams.sortField !== query.sortField || this.cardCacheParams.sortOrder !== query.sortOrder) {
      this.cardCacheParams.sortField = query.sortField;
      this.cardCacheParams.sortOrder = query.sortOrder;
      this.cardCache = sortCache(
        this.cardCache,
        this.cardCacheParams.sortField,
        this.cardCacheParams.sortOrder
      );
    }
    if (this.cardCache.length > 0) {
      let cardsBatch;
      if (acceptableIds && acceptableIds.size > 0) {
        const cardSubcache = createFilteredSubcache(this.cardCache, acceptableIds);
        cardsBatch = extractFromCache(cardSubcache, start1, num);
      } else {
        cardsBatch = extractFromCache(this.cardCache, start1, num);
      }
      return Promise.resolve(cardsBatch);
    }
    const additionalSearchOptions = {
      filter: query.filter,
      sortField: query.sortField,
      sortOrder: query.sortOrder,
      categories: query?.categories ? this.convertSearchCategories(query.categories) : ""
    };
    const searches = [];
    if (primarySolutionsGroupId && !isEnterprise) {
      const auth = userSession ? userSession : new common.UserSession({});
      searches.push(
        common.searchGroupAllContents(
          primarySolutionsGroupId,
          query.q,
          auth,
          additionalSearchOptions,
          portalUrl
        )
      );
    }
    if (agoBasedEnterpriseSolutionsGroupId && isEnterprise) {
      searches.push(
        common.searchGroupAllContents(
          agoBasedEnterpriseSolutionsGroupId,
          query.q,
          anonAgolSession,
          additionalSearchOptions,
          agolPortalUrl
        )
      );
    }
    return Promise.allSettled(searches).then((responseSet) => {
      const fulfilledResponses = [];
      responseSet.forEach((result) => {
        if (result.status === "fulfilled") {
          const searchResult = result.value;
          let templateSourceUrl = "";
          let knownToBePublicSource = false;
          templateSourceUrl = this.agolPortalUrl;
          knownToBePublicSource = true;
          searchResult.results.forEach((item) => {
            item.sourcePortalUrl = templateSourceUrl;
            item.knownToBePublicSource = knownToBePublicSource;
          });
          fulfilledResponses.push(searchResult);
        } else if (result.status === "rejected") {
          throw new Error(
            result.reason.message ? result.reason.message : "cannotAccessAGO"
            // (isPrimary
            // // A failed fetch of the primary group in enterprise or AGO
            // ? result.reason.message
            // // We're in enterprise and configured to search AGO (because agoBasedEnterpriseSolutionsGroupId
            // // is defined), but appear not to be able to reach the internet
            // : "enterpriseCannotAccessAGO"
            // ) as string
          );
        }
      });
      if (fulfilledResponses.length === 0) {
        this.cardCache = [];
      } else if (fulfilledResponses.length === 1) {
        this.cardCache = this.getCardsFromResponse(fulfilledResponses[0]);
      } else {
        this.cardCache = sortCache(
          this.getCardsFromResponse(this.mergeResponses(fulfilledResponses)),
          this.cardCacheParams.sortField,
          this.cardCacheParams.sortOrder
        );
      }
      let cardsBatch;
      if (acceptableIds && acceptableIds.size > 0) {
        const cardSubcache = createFilteredSubcache(this.cardCache, acceptableIds);
        cardsBatch = extractFromCache(cardSubcache, start1, num);
      } else {
        cardsBatch = extractFromCache(this.cardCache, start1, num);
      }
      return Promise.resolve(cardsBatch);
    }).catch((error) => {
      return Promise.reject(new Error(error.message));
    });
  }
  /**
   * Fetches cards for deployed Solutions from the server.
   *
   * @param query AGO query terms and options
   * @param userSession Authentication for thumbnailUrl
   * @returns A collection of deployed Solutions as cards; the paging information shows that all of the cards
   * are returned
   */
  requestDeployedSolutionCards(query, userSession, id = "") {
    const portalUrl = this.portalUrl + "/sharing/rest";
    if (this.cardCacheParams.q !== query.q || this.cardCacheParams.categoriesAsStr !== JSON.stringify(query.q) || query.sortField === "relevance") {
      this.cardCache = [];
      this.cardCacheParams = {
        q: query.q,
        categoriesAsStr: "[]",
        sortField: query.sortField,
        sortOrder: query.sortOrder
      };
    } else if (this.cardCacheParams.sortField !== query.sortField || this.cardCacheParams.sortOrder !== query.sortOrder) {
      this.cardCacheParams.sortField = query.sortField;
      this.cardCacheParams.sortOrder = query.sortOrder;
      this.cardCache = sortCache(
        this.cardCache,
        this.cardCacheParams.sortField,
        this.cardCacheParams.sortOrder
      );
    }
    if (this.cardCache.length > 0) {
      const cardsBatch = extractFromCache(this.cardCache, 1, this.cardCache.length);
      return Promise.resolve(cardsBatch);
    }
    const searchOptions = {
      q: query.q,
      filter: query.filter,
      sortField: query.sortField,
      sortOrder: query.sortOrder,
      authentication: userSession,
      portal: portalUrl,
      categories: query?.categories ? JSON.stringify(query.categories) : "",
      num: query.num
    };
    return id ? common.getItemBase(id, userSession).then((response) => {
      this.cardCache = this.getCardsFromResponse({ results: [response] });
      const cardsBatch = extractFromCache(this.cardCache, 1, this.cardCache.length);
      return Promise.resolve(cardsBatch);
    }).catch((err) => {
      return Promise.reject(new Error(err));
    }) : common.searchAllItems(searchOptions).then((response) => {
      this.cardCache = this.getCardsFromResponse(response);
      const cardsBatch = extractFromCache(this.cardCache, 1, this.cardCache.length);
      return Promise.resolve(cardsBatch);
    }).catch((err) => {
      return Promise.reject(new Error(err));
    });
  }
  // ---------------------------------------------------------------------------------------------------------------- //
  /**
   * Stringifies categories for search.
   *
   * @param categories AGO item categories, e.g., "/Categories/Conservation"
   * or ["/Categories/Conservation", "/Categories/Pipeline"]
   * @returns Categories where each element is a stringified array of categories
   */
  convertSearchCategories(categories) {
    if (categories) {
      if (Array.isArray(categories)) {
        categories = categories.map(
          (andGroup) => JSON.stringify(Array.isArray(andGroup) ? andGroup : [andGroup])
          // force to an array to allow categories with commas
        );
      } else {
        categories = JSON.stringify([categories]);
      }
    }
    return categories;
  }
  /**
   * Constructs Solution cards from a Solution-query response.
   *
   * @param response Response from a query
   * @returns Solution information as cards
   */
  getCardsFromResponse(response) {
    if (response.results.length > 0) {
      const screenedCards = common.sanitizeJSON(response.results);
      const cards = screenedCards.map(
        (result) => {
          const portalUrl = result.sourcePortalUrl ? result.sourcePortalUrl : this.portalUrl;
          const orgUrl = result.sourcePortalUrl ? result.sourcePortalUrl : this.orgUrl;
          const card = {
            id: result.id,
            title: result.title,
            snippet: result.snippet || "",
            description: result.description || "",
            url: result.url || "",
            itemUrl: `${orgUrl}/home/item.html` + createUrlParams([{ k: "id", v: result.id }]) || "",
            thumbnailFilename: result.thumbnail,
            thumbnailUrl: generateThumbnailUrl(
              result.id,
              result.thumbnail,
              this.cMissingImageDataURI,
              portalUrl
            ),
            tryitUrl: result.url || "",
            typeKeywords: result.typeKeywords,
            learnMoreUrl: result.properties?.learnMoreUrl || "",
            createdMs: result.created,
            created: getLocaleLongDateString(result.created, this.locale),
            modified: getLocaleLongDateString(result.modified, this.locale),
            numViews: result.numViews,
            tags: result.tags,
            categories: result.groupCategories && result.groupCategories.length > 0 ? result.groupCategories : result.categories || [],
            licenseInfo: createDivHtml(result.licenseInfo),
            deployCommonId: getTypeKeywordProp(result.typeKeywords || [], "solutionid-"),
            deployVersion: getTypeKeywordProp(result.typeKeywords || [], "solutionversion-"),
            canDelete: result.created > 16183314e5,
            // Only solutions deployed after April 13, 2021 at 9:30PM can be deleted (9.1 release)
            preview: this.preparePreviewImageUrls(result.id, result.properties?.preview, portalUrl),
            sourcePortalUrl: result.sourcePortalUrl || "",
            knownToBePublicSource: result.knownToBePublicSource || false,
            waitId: "",
            relatedSolutions: common.getProp(result, "properties.relatedSolutions") || [],
            owner: result.owner
          };
          if (card.deployCommonId !== "" && card.deployVersion !== "") {
            return card;
          } else {
            return null;
          }
        }
      );
      return cards.filter((card) => card != null);
    } else {
      return [];
    }
  }
  /**
   * Merge a set of search responses into a single response item.
   *
   * @param responseSet Array of search results
   * @returns A response item that takes its query from the first item in the set and sets the other properties
   * as if all of the responses are the result of one, large query that's independent of AGO's 100-item limit.
   */
  mergeResponses(responseSet) {
    let total = 0;
    responseSet.forEach((response) => total += response.total);
    let results = [];
    responseSet.forEach((response) => results = results.concat(response.results));
    return {
      query: responseSet[0].query,
      start: 1,
      num: total,
      nextStart: -1,
      total,
      results
    };
  }
  /**
   * Converts image preview information into a URL pointing to that image; returns non-image previews unchanged.
   *
   * @param id Item id to insert into URL
   * @param preview List of previews to modify
   * @returns Copy of previews with iamge previews modified
   */
  preparePreviewImageUrls(id, preview, sourcePortal) {
    if (!preview) {
      return [];
    }
    return preview.map(
      (preview2) => {
        if (preview2.format === "image") {
          preview2.name = sourcePortal + "/sharing/rest/content/items/" + id + "/resources/" + preview2.name;
        }
        return preview2;
      }
    );
  }
}
async function getDeployedSolutions(auth, userSession, _cardsFetcher, _cardsFetcherDeployed, q = BASE_DEPLOYED_TERMS, sortField = "created", sortOrder = "desc", delay = false, categories = [], allCards = [], owner, id) {
  if (!auth?.IsSignedIn) {
    return;
  }
  const deployedSolnsQuery = {
    q,
    filter: "type:Solution",
    sortField,
    sortOrder,
    delay,
    categories,
    num: 100
  };
  deployedSolnsQuery.q += _getOrgAndOwnerQueryPart(auth, owner);
  return await _requestDeployedSolutionCards(
    userSession,
    deployedSolnsQuery,
    _cardsFetcherDeployed,
    allCards,
    id
  );
}
function _getOrgAndOwnerQueryPart(auth, owner) {
  let suffix = "";
  const sourceOrgId = auth.PortalUserOrg;
  const sourceOrgOwner = auth.PortalUserName;
  if (sourceOrgId) {
    suffix += " orgid:" + sourceOrgId;
  }
  if (owner !== `My organization's solutions` && sourceOrgOwner) {
    suffix += " owner:" + sourceOrgOwner;
  }
  return suffix;
}
async function _requestDeployedSolutionCards(userSession, query, cardsFetcherDeployed, allCards, id = "") {
  const response = await cardsFetcherDeployed.requestDeployedSolutionCards(query, userSession, id);
  const relatedSolutions = getDeployedRelatedSolutionIds(response.cards, allCards);
  return {
    cards: response.cards,
    relatedSolutions
  };
}
export {
  CardsFetcher as C,
  getDeployedSolutions as g
};
