import * as validation from "@jet/environment/json/validation";
import { isNothing, isSome } from "@jet/environment/types/optional";
import { asJSONData } from "../../../foundation/json-parsing/server-data";
import * as productVariant from "../../product-page/product-page-variants";
import * as metricsUtil from "./util";
class MetricsLocationStackItem {
    constructor() {
        this.position = 0;
    }
}
export function newLocationTracker() {
    return {
        rootPosition: 0,
        locationStack: [],
    };
}
/**
 * @param locationTracker The location tracker to copy
 * @returns A copy of the location tracker
 */
export function createLocationTrackerCopy(locationTracker) {
    const locationStackCopy = [];
    for (const locationStackEntry of locationTracker.locationStack) {
        locationStackCopy.push({
            ...locationStackEntry,
        });
    }
    return {
        rootPosition: locationTracker.rootPosition,
        locationStack: locationStackCopy,
    };
}
export function createContentLocation(objectGraph, options, title) {
    const locations = stackItemsToLocationStack(options.locationTracker);
    const contentLocation = newContentLocation(objectGraph, options, title);
    return [contentLocation, ...locations];
}
export function createBasicLocation(objectGraph, options, title) {
    const locations = stackItemsToLocationStack(options.locationTracker);
    const basicLocation = newBasicLocation(objectGraph, options, title);
    return [basicLocation, ...locations];
}
export function pushContentLocation(objectGraph, options, title) {
    const stackItem = new MetricsLocationStackItem();
    stackItem.location = newContentLocation(objectGraph, options, title);
    options.locationTracker.locationStack.unshift(stackItem);
}
export function pushBasicLocation(objectGraph, options, title) {
    const stackItem = new MetricsLocationStackItem();
    stackItem.location = newBasicLocation(objectGraph, options, title);
    options.locationTracker.locationStack.unshift(stackItem);
}
export function popLocation(tracker) {
    if (tracker.locationStack.length === 0) {
        validation.unexpectedType("ignoredValue", "non-empty location stack", "empty location stack");
        return;
    }
    tracker.locationStack.shift();
}
export function currentPosition(tracker) {
    const stackItem = lastStackItemAdded(tracker);
    if (stackItem) {
        return stackItem.position;
    }
    else {
        return tracker.rootPosition;
    }
}
export function previousPosition(tracker) {
    if (tracker.locationStack.length < 2) {
        return null;
    }
    return tracker.locationStack[1].position;
}
export function currentLocation(tracker) {
    const stackItem = lastStackItemAdded(tracker);
    if (stackItem) {
        return stackItem.location;
    }
    else {
        return null;
    }
}
/**
 * Set current position of tracker. This is necessary when large today modules are broken apart into multipart shelves.
 * We need to preserve the position of content within server-response, not our logical shelves.
 * @param tracker Tracker update position of.
 * @param position Position to set to.
 */
export function setCurrentPosition(tracker, position) {
    const stackItem = lastStackItemAdded(tracker);
    if (stackItem) {
        stackItem.position = position;
    }
    else {
        tracker.rootPosition = position;
    }
}
export function nextPosition(tracker) {
    const stackItem = lastStackItemAdded(tracker);
    if (stackItem) {
        stackItem.position++;
    }
    else {
        tracker.rootPosition++;
    }
}
function newContentLocation(objectGraph, options, title) {
    var _a;
    const base = newBasicLocation(objectGraph, options, title);
    // Use the location tracker if there is no id override
    if (!options.id && options.locationTracker) {
        base.idType = "sequential";
        base.id = currentPosition(options.locationTracker).toString();
    }
    else {
        // If there is a id specified, use that
        const idType = metricsUtil.idTypeForMetricsOptions(options);
        if (isSome(idType)) {
            base.idType = idType;
        }
        let id = options.id;
        if ((_a = options.anonymizationOptions) === null || _a === void 0 ? void 0 : _a.anonymizationString) {
            id = options.anonymizationOptions.anonymizationString;
        }
        base.id = isNothing(id) ? "" : id;
    }
    if (options.fcKind) {
        base.fcKind = options.fcKind;
    }
    if (options.displayStyle) {
        base.displayStyle = options.displayStyle;
    }
    if (options.inAppEventId) {
        base.inAppEventId = options.inAppEventId;
    }
    if (options.relatedSubjectIds) {
        base.relatedSubjectIds = options.relatedSubjectIds;
    }
    if (options.canonicalId) {
        base.canonicalId = options.canonicalId;
    }
    if (options.optimizationEntityId) {
        base.optimizationEntityId = options.optimizationEntityId;
    }
    if (options.optimizationId) {
        base.optimizationId = options.optimizationId;
    }
    if (isSome(options.rowIndex)) {
        base.rowIndex = options.rowIndex;
    }
    if (options.productVariantData) {
        Object.assign(base, productVariant.contentFieldsForProductVariantData(options.productVariantData));
    }
    return base;
}
function newBasicLocation(objectGraph, options, title) {
    var _a, _b;
    let name = title;
    if ((_a = options.anonymizationOptions) === null || _a === void 0 ? void 0 : _a.anonymizationString) {
        name = options.anonymizationOptions.anonymizationString;
    }
    const location = {
        locationPosition: currentPosition(options.locationTracker),
        locationType: metricsUtil.targetTypeForMetricsOptions(objectGraph, options),
        name: isNothing(name) ? "" : name,
    };
    if (isSome(options.badges)) {
        location.badges = (_b = asJSONData(options.badges)) !== null && _b !== void 0 ? _b : undefined;
    }
    if (options.recoMetricsData) {
        Object.assign(location, options.recoMetricsData);
    }
    return location;
}
function stackItemsToLocationStack(tracker) {
    return tracker.locationStack.map((stackItem) => {
        return stackItem.location;
    });
}
function lastStackItemAdded(tracker) {
    const length = tracker.locationStack.length;
    if (length === 0) {
        return null;
    }
    return tracker.locationStack[0];
}
//# sourceMappingURL=location.js.map