// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { assertNotReachedCase } from '//resources/js/assert.js';
import { loadTimeData } from '//resources/js/load_time_data.js';
import { ContextUploadErrorType, ContextUploadStatus, InputType, ModelMode, ToolMode } from './composebox_query.mojom-webui.js';
// LINT.IfChange(FileValidationError)
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
export var ComposeboxFileValidationError;
(function (ComposeboxFileValidationError) {
    ComposeboxFileValidationError[ComposeboxFileValidationError["NONE"] = 0] = "NONE";
    ComposeboxFileValidationError[ComposeboxFileValidationError["TOO_MANY_FILES"] = 1] = "TOO_MANY_FILES";
    ComposeboxFileValidationError[ComposeboxFileValidationError["FILE_EMPTY"] = 2] = "FILE_EMPTY";
    ComposeboxFileValidationError[ComposeboxFileValidationError["FILE_SIZE_TOO_LARGE"] = 3] = "FILE_SIZE_TOO_LARGE";
    ComposeboxFileValidationError[ComposeboxFileValidationError["MAX_VALUE"] = 3] = "MAX_VALUE";
})(ComposeboxFileValidationError || (ComposeboxFileValidationError = {}));
// LINT.ThenChange(//tools/metrics/histograms/metadata/contextual_search/enums.xml:FileValidationError)
// LINT.IfChange(ContextType)
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
export var ContextType;
(function (ContextType) {
    ContextType[ContextType["TAB"] = 0] = "TAB";
    ContextType[ContextType["FILE"] = 1] = "FILE";
    ContextType[ContextType["IMAGE"] = 2] = "IMAGE";
    ContextType[ContextType["IMAGE_GEN"] = 3] = "IMAGE_GEN";
    ContextType[ContextType["DEEP_RESEARCH"] = 4] = "DEEP_RESEARCH";
    ContextType[ContextType["CANVAS"] = 5] = "CANVAS";
    ContextType[ContextType["AUTO_MODEL"] = 6] = "AUTO_MODEL";
    ContextType[ContextType["THINKING_MODEL"] = 7] = "THINKING_MODEL";
    ContextType[ContextType["REGULAR_MODEL"] = 8] = "REGULAR_MODEL";
    ContextType[ContextType["PRO_NO_GEN_UI_MODEL"] = 9] = "PRO_NO_GEN_UI_MODEL";
    ContextType[ContextType["UNKNOWN"] = 10] = "UNKNOWN";
    ContextType[ContextType["DRIVE"] = 11] = "DRIVE";
    ContextType[ContextType["MAX_VALUE"] = 11] = "MAX_VALUE";
})(ContextType || (ContextType = {}));
// LINT.ThenChange(//components/omnibox/common/omnibox_metrics_utils.h:ContextType,
// //tools/metrics/histograms/metadata/contextual_search/enums.xml:ContextType)
// These values are sorted by precedence. The error with the highest value
// will be the one shown to the user if multiple errors apply.
export var ProcessFilesError;
(function (ProcessFilesError) {
    ProcessFilesError[ProcessFilesError["NONE"] = 0] = "NONE";
    ProcessFilesError[ProcessFilesError["INVALID_TYPE"] = 1] = "INVALID_TYPE";
    ProcessFilesError[ProcessFilesError["FILE_TOO_LARGE"] = 2] = "FILE_TOO_LARGE";
    ProcessFilesError[ProcessFilesError["FILE_EMPTY"] = 3] = "FILE_EMPTY";
    ProcessFilesError[ProcessFilesError["MAX_FILES_EXCEEDED"] = 4] = "MAX_FILES_EXCEEDED";
    ProcessFilesError[ProcessFilesError["MAX_IMAGES_EXCEEDED"] = 5] = "MAX_IMAGES_EXCEEDED";
    ProcessFilesError[ProcessFilesError["MAX_PDFS_EXCEEDED"] = 6] = "MAX_PDFS_EXCEEDED";
    ProcessFilesError[ProcessFilesError["FILE_UPLOAD_NOT_ALLOWED"] = 7] = "FILE_UPLOAD_NOT_ALLOWED";
})(ProcessFilesError || (ProcessFilesError = {}));
export var TabSuggestionsState;
(function (TabSuggestionsState) {
    TabSuggestionsState[TabSuggestionsState["NOT_STARTED"] = 0] = "NOT_STARTED";
    TabSuggestionsState[TabSuggestionsState["LOADING"] = 1] = "LOADING";
    TabSuggestionsState[TabSuggestionsState["LOADED"] = 2] = "LOADED";
})(TabSuggestionsState || (TabSuggestionsState = {}));
export const FILE_VALIDATION_ERRORS_MAP = new Map([
    [
        ContextUploadErrorType.kBrowserProcessingError,
        'composeboxFileUploadFailed',
    ],
    [
        ContextUploadErrorType.kImageProcessingError,
        'composeFileTypesAllowedError',
    ],
    [
        ContextUploadErrorType.kServerSizeLimitExceeded,
        'composeboxFileUploadInvalidTooLarge',
    ],
    [
        ContextUploadErrorType.kUnknown,
        'composeboxFileUploadValidationFailed',
    ],
    [
        ContextUploadErrorType.kBrowserProcessingFileTooLargeError,
        'composeboxFileUploadInvalidTooLarge',
    ],
    [
        ContextUploadErrorType.kBrowserProcessingFileEmptyError,
        'composeboxFileUploadInvalidEmptySize',
    ],
    [
        ContextUploadErrorType.kBrowserProcessingMaxFilesExceededError,
        'maxFilesReachedError',
    ],
    [
        ContextUploadErrorType.kBrowserProcessingUnsupportedFileTypeError,
        'composeFileTypesAllowedError',
    ],
    [
        ContextUploadErrorType.kBrowserProcessingFileUploadNotAllowedError,
        'composeboxFileUploadNotAllowed',
    ],
    [
        ContextUploadErrorType.kBrowserProcessingMaxImagesExceededError,
        'maxImagesReachedError',
    ],
    [
        ContextUploadErrorType.kBrowserProcessingMaxPdfsExceededError,
        'maxPdfsReachedError',
    ],
]);
export class ComposeboxFile {
    uuid;
    name;
    objectUrl;
    dataUrl;
    type;
    inputType;
    status;
    url;
    tabId;
    isDeletable;
    iconName;
    supportsUnimodal;
    thumbnailUrl;
    iconUrl;
    constructor(uuid, name, type, inputType, options) {
        this.uuid = uuid;
        this.name = name;
        this.type = type;
        this.inputType = inputType;
        this.objectUrl = options?.objectUrl ?? null;
        this.dataUrl = options?.dataUrl ?? null;
        this.status = options?.status ?? ContextUploadStatus.kNotUploaded;
        this.url = options?.url ?? null;
        this.tabId = options?.tabId ?? null;
        this.isDeletable = options?.isDeletable ?? true;
        this.iconName = options?.iconName ?? null;
        this.supportsUnimodal = options?.supportsUnimodal ?? false;
        this.thumbnailUrl = options?.thumbnailUrl ?? null;
        this.iconUrl = options?.iconUrl ?? null;
    }
    static createFromFile(uuid, file, status = ContextUploadStatus.kNotUploaded, options) {
        const inputType = file.type.includes('image') ? InputType.kLensImage :
            InputType.kLensFile;
        return new ComposeboxFile(uuid, file.name, file.type, inputType, {
            status,
            ...options,
        });
    }
    static createFromTab(uuid, tabId, title, url, options) {
        return new ComposeboxFile(uuid, title, 'tab', InputType.kBrowserTab, {
            status: ContextUploadStatus.kUploadSuccessful,
            tabId,
            url,
            ...options,
        });
    }
    static createFromInjectedInput(uuid, dataUrl, name = 'Pasted Image', iconName = null) {
        return new ComposeboxFile(uuid, name, 'injectedinput', InputType.kLensImage, {
            dataUrl,
            objectUrl: dataUrl,
            status: ContextUploadStatus.kUploadSuccessful,
            iconName,
        });
    }
}
export var TabUploadOrigin;
(function (TabUploadOrigin) {
    TabUploadOrigin[TabUploadOrigin["CONTEXT_MENU"] = 0] = "CONTEXT_MENU";
    TabUploadOrigin[TabUploadOrigin["RECENT_TAB_CHIP"] = 1] = "RECENT_TAB_CHIP";
    TabUploadOrigin[TabUploadOrigin["ACTION_CHIP"] = 2] = "ACTION_CHIP";
    TabUploadOrigin[TabUploadOrigin["AUTO_ACTIVE"] = 3] = "AUTO_ACTIVE";
    TabUploadOrigin[TabUploadOrigin["OTHER"] = 4] = "OTHER";
})(TabUploadOrigin || (TabUploadOrigin = {}));
export var GlifAnimationState;
(function (GlifAnimationState) {
    GlifAnimationState["INELIGIBLE"] = "ineligible";
    GlifAnimationState["SPINNER_ONLY"] = "spinner-only";
    GlifAnimationState["STARTED"] = "started";
    GlifAnimationState["FINISHED"] = "finished";
})(GlifAnimationState || (GlifAnimationState = {}));
// LINT.IfChange(ContextualSearchInputStateDeletionType)
export var ContextualSearchInputStateDeletionType;
(function (ContextualSearchInputStateDeletionType) {
    ContextualSearchInputStateDeletionType[ContextualSearchInputStateDeletionType["FILE"] = 0] = "FILE";
    ContextualSearchInputStateDeletionType[ContextualSearchInputStateDeletionType["TAB"] = 1] = "TAB";
    ContextualSearchInputStateDeletionType[ContextualSearchInputStateDeletionType["TOOL"] = 2] = "TOOL";
    ContextualSearchInputStateDeletionType[ContextualSearchInputStateDeletionType["MAX_VALUE"] = 2] = "MAX_VALUE";
})(ContextualSearchInputStateDeletionType || (ContextualSearchInputStateDeletionType = {}));
// LINT.ThenChange(//tools/metrics/histograms/metadata/contextual_search/enums.xml:ContextualSearchInputStateDeletionType)
export function recordEnumerationValue(metricName, value, enumSize) {
    chrome.histograms.recordEnumerationValue(metricName, value, enumSize);
}
export function recordUserAction(metricName) {
    chrome.histograms.recordUserAction(metricName);
}
export function recordBoolean(metricName, value) {
    chrome.histograms.recordBoolean(metricName, value);
}
// TODO(crbug.com/468329884): Consider making this a new contextual entry
// source so the realbox and composebox don't both get logged as NTP.
export function recordContextAdditionMethod(additionMethod, composeboxSource) {
    recordEnumerationValue('ContextualSearch.ContextAdded.ContextAddedMethod.' + composeboxSource, additionMethod, 3 /* ComposeboxContextAddedMethod.MAX_VALUE */ + 1);
}
// LINT.IfChange(getContextTypeString)
function getContextTypeString(type) {
    switch (type) {
        case ContextType.TAB:
            return 'Tab';
        case ContextType.FILE:
            return 'File';
        case ContextType.IMAGE:
            return 'Image';
        case ContextType.IMAGE_GEN:
            return 'ImageGen';
        case ContextType.DEEP_RESEARCH:
            return 'DeepResearch';
        case ContextType.DRIVE:
            return 'Drive';
        case ContextType.CANVAS:
            return 'Canvas';
        case ContextType.AUTO_MODEL:
            return 'AutoModel';
        case ContextType.THINKING_MODEL:
            return 'ThinkingModel';
        case ContextType.REGULAR_MODEL:
            return 'RegularModel';
        case ContextType.PRO_NO_GEN_UI_MODEL:
            return 'ProNoGenUiModel';
        case ContextType.UNKNOWN:
            return 'Unknown';
        default:
            return 'Unknown';
    }
}
// LINT.ThenChange(//components/omnibox/common/omnibox_metrics_utils.cc:GetContextTypeString)
export function recordContextualElementClickedMetric(composeboxSource, popupType, contextType) {
    const metricName = `${composeboxSource}.AimEntrypoint.${popupType}.ContextualElement.Clicked`;
    recordEnumerationValue(metricName, contextType, ContextType.MAX_VALUE + 1);
    recordUserAction(`${metricName}.${getContextTypeString(contextType)}`);
}
export function recordContextualElementShownMetric(composeboxSource, popupType, contextType) {
    const metricName = `${composeboxSource}.AimEntrypoint.${popupType}.ContextualElement.Shown`;
    recordEnumerationValue(metricName, contextType, ContextType.MAX_VALUE + 1);
}
export function recordToolModeSelection(mode, composeboxSource, popupType) {
    let contextType = ContextType.UNKNOWN;
    switch (mode) {
        case ToolMode.kImageGen:
            contextType = ContextType.IMAGE_GEN;
            break;
        case ToolMode.kDeepSearch:
            contextType = ContextType.DEEP_RESEARCH;
            break;
        case ToolMode.kCanvas:
            contextType = ContextType.CANVAS;
            break;
        default:
            break;
    }
    recordContextualElementClickedMetric(composeboxSource, popupType, contextType);
}
export function recordToolModeShown(mode, composeboxSource, popupType) {
    let contextType = ContextType.UNKNOWN;
    switch (mode) {
        case ToolMode.kImageGen:
            contextType = ContextType.IMAGE_GEN;
            break;
        case ToolMode.kDeepSearch:
            contextType = ContextType.DEEP_RESEARCH;
            break;
        case ToolMode.kCanvas:
            contextType = ContextType.CANVAS;
            break;
        default:
            break;
    }
    recordContextualElementShownMetric(composeboxSource, popupType, contextType);
}
export function recordModelModeSelection(model, composeboxSource, popupType) {
    let contextType = ContextType.UNKNOWN;
    switch (model) {
        case ModelMode.kGeminiRegular:
            contextType = ContextType.REGULAR_MODEL;
            break;
        case ModelMode.kGeminiPro:
            contextType = ContextType.THINKING_MODEL;
            break;
        case ModelMode.kGeminiProAutoroute:
            contextType = ContextType.AUTO_MODEL;
            break;
        case ModelMode.kGeminiProNoGenUi:
            contextType = ContextType.PRO_NO_GEN_UI_MODEL;
            break;
        default:
            break;
    }
    recordContextualElementClickedMetric(composeboxSource, popupType, contextType);
}
export function recordModelModeShown(model, composeboxSource, popupType) {
    let contextType = ContextType.UNKNOWN;
    switch (model) {
        case ModelMode.kGeminiRegular:
            contextType = ContextType.REGULAR_MODEL;
            break;
        case ModelMode.kGeminiPro:
            contextType = ContextType.THINKING_MODEL;
            break;
        case ModelMode.kGeminiProAutoroute:
            contextType = ContextType.AUTO_MODEL;
            break;
        case ModelMode.kGeminiProNoGenUi:
            contextType = ContextType.PRO_NO_GEN_UI_MODEL;
            break;
        default:
            break;
    }
    recordContextualElementShownMetric(composeboxSource, popupType, contextType);
}
export function recordInputTypeShown(type, composeboxSource, popupType) {
    let contextType = ContextType.UNKNOWN;
    switch (type) {
        case InputType.kLensFile:
            contextType = ContextType.FILE;
            break;
        case InputType.kLensImage:
            contextType = ContextType.IMAGE;
            break;
        case InputType.kBrowserTab:
            contextType = ContextType.TAB;
            break;
        case InputType.kDrive:
            contextType = ContextType.DRIVE;
            break;
        default:
            break;
    }
    recordContextualElementShownMetric(composeboxSource, popupType, contextType);
}
export function hasAllowedInputs(inputState, usePecApi) {
    if (!usePecApi) {
        return true;
    }
    return !!inputState &&
        (inputState.allowedModels.length > 0 ||
            inputState.allowedTools.length > 0 ||
            inputState.allowedInputTypes.length > 0);
}
/**
 * Helper to retrieve a boolean from loadTimeData with a fallback if the
 * value hasn't been set.
 */
// TODO(b/474406096): As part of componentization, the use of
// `loadTimeData.valueExists` in this file should be removed and the
// per-embedder behavior migrated into the relevant embedder. If a feature does
// still need to exist in the base component, it should become a property
// instead.
export function getLoadTimeBoolean(id, defaultValue) {
    return loadTimeData.valueExists(id) ? loadTimeData.getBoolean(id) :
        defaultValue;
}
export function isContextUploadStatusTerminal(status) {
    switch (status) {
        case ContextUploadStatus.kUploadSuccessful:
        case ContextUploadStatus.kUploadFailed:
        case ContextUploadStatus.kValidationFailed:
        case ContextUploadStatus.kUploadExpired:
        case ContextUploadStatus.kUploadReplaced:
            return true;
        case ContextUploadStatus.kNotUploaded:
        case ContextUploadStatus.kProcessing:
        case ContextUploadStatus.kUploadStarted:
        case ContextUploadStatus.kProcessingSuggestSignalsReady:
            return false;
        default:
            assertNotReachedCase(status, 'Unknown enum value');
    }
}
export function mapUploadErrorToProcessFilesError(errorType) {
    switch (errorType) {
        case ContextUploadErrorType.kBrowserProcessingFileTooLargeError:
            return ProcessFilesError.FILE_TOO_LARGE;
        case ContextUploadErrorType.kBrowserProcessingFileEmptyError:
            return ProcessFilesError.FILE_EMPTY;
        case ContextUploadErrorType.kBrowserProcessingMaxFilesExceededError:
            return ProcessFilesError.MAX_FILES_EXCEEDED;
        case ContextUploadErrorType.kBrowserProcessingUnsupportedFileTypeError:
            return ProcessFilesError.INVALID_TYPE;
        case ContextUploadErrorType.kBrowserProcessingFileUploadNotAllowedError:
            return ProcessFilesError.FILE_UPLOAD_NOT_ALLOWED;
        case ContextUploadErrorType.kBrowserProcessingMaxImagesExceededError:
            return ProcessFilesError.MAX_IMAGES_EXCEEDED;
        case ContextUploadErrorType.kBrowserProcessingMaxPdfsExceededError:
            return ProcessFilesError.MAX_PDFS_EXCEEDED;
        default:
            return ProcessFilesError.NONE;
    }
}
