"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.searchPortalUsersLegacy = searchPortalUsersLegacy;
exports.searchPortalUsers = searchPortalUsers;
exports.searchCommunityUsers = searchCommunityUsers;
const arcgis_rest_portal_1 = require("@esri/arcgis-rest-portal");
const serializeQueryForPortal_1 = require("../serializeQueryForPortal");
const HubError_1 = require("../../HubError");
const getNextPortalCallback_1 = require("./commonHelpers/getNextPortalCallback");
const expandPredicate_1 = require("./expandPredicate");
const util_1 = require("../../util");
const utils_1 = require("../utils");
const HubUsers_1 = require("../../users/HubUsers");
function buildSearchOptions(query, options, operation) {
    // requestOptions is always required and user must be authd
    if (!options.requestOptions) {
        throw new HubError_1.default(operation, "requestOptions: IHubRequestOptions is required.");
    }
    if (!options.requestOptions.authentication) {
        throw new HubError_1.default(operation, "requestOptions must pass authentication.");
    }
    const clonedQuery = (0, util_1.cloneObject)(query);
    // Expand the individual predicates in each filter
    clonedQuery.filters = clonedQuery.filters.map((filter) => {
        filter.predicates = filter.predicates.map(expandPredicate_1.expandPredicate);
        return filter;
    });
    // Serialize the all the groups for portal
    const so = (0, serializeQueryForPortal_1.serializeQueryForPortal)(clonedQuery);
    // Array of properties we want to copy from IHubSearchOptions to the ISearchOptions
    const props = [
        "num",
        "sortField",
        "sortOrder",
        "include",
        "start",
        "requestOptions",
    ];
    // copy the props over
    props.forEach((prop) => {
        if (Object.prototype.hasOwnProperty.call(options, prop)) {
            so[prop] = options[prop];
        }
    });
    // Unlike Groups and Item, the Users api *requires* authentication
    // so we set it directly
    so.authentication = options.requestOptions.authentication;
    return so;
}
/**
 * @private
 *
 * Portal Search Implementation for Users within the currently authenticated user's organization.
 * Automatically adds "org.name as OrgName" enrichment
 *
 * DEPRECATED: This method will be deprecated in a future release, as it's not ideal to impose default enrichments in all
 * cases. When this method is depreated, all places that currently call `hubSearch` with a `targetEntity` of `user` will
 * need to be updated to use the `portalUser` `targetEntity` and explicitly pass `"org.name as OrgName"` in `inclues` to
 * preserve that enrichment, if needed. E.g.
 *
 * ```js
 * // before
 * await hubSearch(
 *   { targetEntity: "user", ... },
 *   { start: 1, ... },
 * );
 *
 * // after
 * await hubSearch(
 *   { targetEntity: "portalUser", ... },
 *   { start: 1, include: ["org.name as OrgName", ...], ... },
 * );
 * ```
 *
 * @param query An IQuery object representing the query to serialize
 * @param options An IHubSearchOptions of search options
 * @returns a promise that resolves an IHubSearchResponse<IHubSearchResult> of users results
 */
function searchPortalUsersLegacy(query, options) {
    const searchOptions = buildSearchOptions(query, options, "searchPortalUsersLegacy");
    // Execute search
    return searchPortal(Object.assign(Object.assign({}, searchOptions), { include: ["org.name as OrgName", ...(searchOptions.include || [])] }));
}
/**
 * @private
 *
 * Portal Search Implementation for Users within the currently authenticated user's organization.
 * No enrichments added by default.
 *
 * @param query An IQuery object representing the query to serialize
 * @param options An IHubSearchOptions of search options
 * @returns a promise that resolves an IHubSearchResponse<IHubSearchResult> of users results
 */
function searchPortalUsers(query, options) {
    const searchOptions = buildSearchOptions(query, options, "searchPortalUsers");
    // Execute search
    return searchPortal(searchOptions);
}
/**
 * @private
 *
 * Community Search Implementation for Users within in any organization.
 * No enrichments added by default.
 *
 * @param query An IQuery object representing the query to serialize
 * @param options An IHubSearchOptions of search options
 * @returns a promise that resolves an IHubSearchResponse<IHubSearchResult> of users results
 */
function searchCommunityUsers(query, options) {
    const searchOptions = buildSearchOptions(query, options, "searchCommunityUsers");
    // Execute search
    return searchCommunity(searchOptions);
}
/**
 * @private
 * @param searchOptions An IUserSearchOptions object
 * @param searchResponse A ISearchResult<IUser> object
 * @returns
 */
function mapUsersToSearchResults(searchOptions, searchResponse) {
    // create mappable fn that will close
    // over the includes and requestOptions
    const fn = (user) => userToSearchResult(user, searchOptions.include, searchOptions.requestOptions);
    return Promise.all(searchResponse.results.map(fn));
}
/**
 * Internal portal search, which then converts `IGroup`s to `IHubSearchResult`s
 * handling enrichments & includes along the way
 *
 * @param searchOptions
 * @returns a promise that resolves enriched internal portal user search results
 */
async function searchPortal(searchOptions) {
    // Execute portal search
    const resp = await (0, arcgis_rest_portal_1.searchUsers)(searchOptions);
    // map over results
    const results = await mapUsersToSearchResults(searchOptions, resp);
    // Group Search does not support aggregations
    // Construct the return
    return {
        total: resp.total,
        results,
        hasNext: resp.nextStart > -1,
        next: (0, getNextPortalCallback_1.getNextPortalCallback)(searchOptions, resp.nextStart, resp.total, searchPortal),
        executedQuerySize: (0, utils_1.getKilobyteSizeOfQuery)(searchOptions.q),
    };
}
/**
 * Community search, which then converts `IGroup`s to `IHubSearchResult`s
 * handling enrichments & includes along the way
 *
 * @param searchOptions
 * @returns a promise that resolves enriched community user search results
 */
async function searchCommunity(searchOptions) {
    // Execute portal search
    const resp = await (0, arcgis_rest_portal_1.searchCommunityUsers)(searchOptions);
    // map over results
    const results = await mapUsersToSearchResults(searchOptions, resp);
    // Group Search does not support aggregations
    // Construct the return
    return {
        total: resp.total,
        results,
        hasNext: resp.nextStart > -1,
        next: (0, getNextPortalCallback_1.getNextPortalCallback)(searchOptions, resp.nextStart, resp.total, searchCommunity),
        executedQuerySize: (0, utils_1.getKilobyteSizeOfQuery)(searchOptions.q),
    };
}
/**
 * Convert an Item to a IHubSearchResult
 * Fetches the includes and attaches them to the item
 * @param item
 * @param include
 * @param requestOptions
 * @returns
 */
function userToSearchResult(user, include = [], requestOptions) {
    // Delegate to HubUsers module
    // This layer of indirection is not necessary but
    // aligns with how the items search works and
    // allows for future specialization
    return (0, HubUsers_1.enrichUserSearchResult)(user, include, requestOptions);
}
//# sourceMappingURL=portalSearchUsers.js.map