"use strict";
/*---------------------------------------------------------------------------------------------
 * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
 * See LICENSE.md in the project root for license terms and full copyright notice.
 *--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Base
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.addRemovedTab = exports.removeTab = exports.removeTabFromWidget = exports.insertTabToWidget = exports.addTabToWidget = exports.addTab = exports.updateSavedTabState = exports.updateTabState = exports.createDraggedTabState = exports.createTabState = void 0;
const immer_1 = require("immer");
const appui_abstract_1 = require("@itwin/appui-abstract");
const NineZoneStateHelpers_1 = require("./NineZoneStateHelpers");
const TabLocation_1 = require("../TabLocation");
const WidgetStateHelpers_1 = require("./WidgetStateHelpers");
const WidgetRestoreState_1 = require("../WidgetRestoreState");
const core_react_1 = require("@itwin/core-react");
const NineZone_1 = require("../../base/NineZone");
const PanelStateHelpers_1 = require("./PanelStateHelpers");
/** @internal */
function createTabState(id, args) {
    return {
        label: "",
        ...args,
        id,
        unloaded: false,
    };
}
exports.createTabState = createTabState;
/** @internal */
function createDraggedTabState(tabId, args) {
    return {
        home: {
            side: "left",
            widgetId: "",
            widgetIndex: 0,
        },
        position: { x: 0, y: 0 },
        ...args,
        tabId,
    };
}
exports.createDraggedTabState = createDraggedTabState;
/** @internal */
function updateTabState(state, id, update) {
    // eslint-disable-next-line deprecation/deprecation
    if (!(id in state.tabs))
        throw new appui_abstract_1.UiError(NineZoneStateHelpers_1.category, "Tab does not exist");
    return (0, immer_1.default)(state, (draft) => {
        const tab = draft.tabs[id];
        update(tab);
    });
}
exports.updateTabState = updateTabState;
/** @internal */
function updateSavedTabState(state, id, update) {
    return (0, immer_1.default)(state, (draft) => {
        const allIds = draft.savedTabs.allIds;
        const byId = draft.savedTabs.byId;
        let tab = byId[id];
        if (!tab) {
            allIds.push(id);
            tab = byId[id] = { id };
        }
        else {
            const index = allIds.indexOf(id);
            allIds.splice(index, 1);
            allIds.push(id);
        }
        update(tab);
    });
}
exports.updateSavedTabState = updateSavedTabState;
/** Adds a new `tab`.
 * @internal
 */
function addTab(state, id, tabArgs) {
    // eslint-disable-next-line deprecation/deprecation
    if (id in state.tabs)
        throw new appui_abstract_1.UiError(NineZoneStateHelpers_1.category, "Tab already exists");
    const tab = {
        ...createTabState(id),
        ...tabArgs,
    };
    return (0, immer_1.default)(state, (stateDraft) => {
        stateDraft.tabs[id] = (0, immer_1.castDraft)(tab);
    });
}
exports.addTab = addTab;
/** Adds an existing `tab` to a specified `widget`.
 * @internal
 */
function addTabToWidget(state, tabId, widgetId) {
    return insertTabToWidget(state, tabId, widgetId, Infinity);
}
exports.addTabToWidget = addTabToWidget;
/** Inserts an existing `tab` to a specified `widget` at a specified `tabIndex`.
 * @internal
 */
function insertTabToWidget(state, tabId, widgetId, tabIndex) {
    if (!(tabId in state.tabs))
        // eslint-disable-next-line deprecation/deprecation
        throw new appui_abstract_1.UiError(NineZoneStateHelpers_1.category, "Tab does not exist", undefined, () => ({
            tabId,
        }));
    (0, WidgetStateHelpers_1.assertWidgetState)(state, widgetId);
    const location = (0, TabLocation_1.getTabLocation)(state, tabId);
    if (location)
        // eslint-disable-next-line deprecation/deprecation
        throw new appui_abstract_1.UiError(NineZoneStateHelpers_1.category, "Tab is already in a widget", undefined, () => ({ tabId, widgetId: location.widgetId }));
    return (0, immer_1.default)(state, (draft) => {
        const widget = (0, WidgetStateHelpers_1.getWidgetState)(draft, widgetId);
        widget.tabs.splice(tabIndex, 0, tabId);
    });
}
exports.insertTabToWidget = insertTabToWidget;
/** Removes tab from the UI, but keeps the tab state.
 * @internal
 */
function removeTabFromWidget(state, tabId) {
    const location = (0, TabLocation_1.getTabLocation)(state, tabId);
    if (!location)
        return state;
    const widgetId = location.widgetId;
    const widget = (0, WidgetStateHelpers_1.getWidgetState)(state, widgetId);
    const tabs = [...widget.tabs];
    const tabIndex = tabs.indexOf(tabId);
    tabs.splice(tabIndex, 1);
    if (tabs.length === 0) {
        return (0, WidgetStateHelpers_1.removeWidget)(state, widgetId);
    }
    if (tabId === widget.activeTabId) {
        state = (0, WidgetStateHelpers_1.setWidgetActiveTabId)(state, widget.id, tabs[0]);
    }
    return (0, WidgetStateHelpers_1.updateWidgetState)(state, widgetId, {
        tabs,
    });
}
exports.removeTabFromWidget = removeTabFromWidget;
/** Removes tab from the UI and deletes the tab state.
 * @internal
 */
function removeTab(state, tabId) {
    // eslint-disable-next-line deprecation/deprecation
    if (!(tabId in state.tabs))
        throw new appui_abstract_1.UiError(NineZoneStateHelpers_1.category, "Tab does not exist");
    state = removeTabFromWidget(state, tabId);
    return (0, immer_1.default)(state, (draft) => {
        delete draft.tabs[tabId];
        if (draft.toolSettings?.tabId === tabId) {
            draft.toolSettings = undefined;
        }
    });
}
exports.removeTab = removeTab;
const defaultHomeState = {
    side: "left",
    widgetId: "",
    widgetIndex: 0,
    tabIndex: 0,
};
/** Adds removed tab to the UI.
 * @internal
 */
function addRemovedTab(state, tabId) {
    if (!(tabId in state.tabs))
        // eslint-disable-next-line deprecation/deprecation
        throw new appui_abstract_1.UiError(NineZoneStateHelpers_1.category, "Tab does not exist", undefined, () => ({
            tabId,
        }));
    const savedTab = state.savedTabs.byId[tabId];
    const home = savedTab?.home || defaultHomeState;
    const { tabIndex, widgetId } = home;
    // Add to an existing widget (by widget id).
    if (widgetId in state.widgets) {
        return insertTabToWidget(state, tabId, widgetId, tabIndex);
    }
    // Add to a floating widget.
    if ((0, WidgetRestoreState_1.isFloatingWidgetRestoreState)(home)) {
        // Add to a new floating widget.
        const nzBounds = core_react_1.Rectangle.createFromSize(state.size);
        const bounds = core_react_1.Rectangle.create(home.floatingWidget.bounds).containIn(nzBounds);
        return (0, WidgetStateHelpers_1.addFloatingWidget)(state, widgetId, [tabId], {
            ...home.floatingWidget,
            bounds: bounds.toProps(),
        });
    }
    // Add to a panel section.
    const panel = state.panels[home.side];
    // Add to existing panel section.
    if (panel.widgets.length >= panel.maxWidgetCount) {
        const sectionIndex = Math.min(panel.maxWidgetCount - 1, home.widgetIndex);
        const sectionId = panel.widgets[sectionIndex];
        return insertTabToWidget(state, tabId, sectionId, home.tabIndex);
    }
    // Create a new panel section.
    const newSectionId = (0, NineZone_1.getUniqueId)();
    return (0, PanelStateHelpers_1.insertPanelWidget)(state, panel.side, newSectionId, [tabId], home.widgetIndex);
}
exports.addRemovedTab = addRemovedTab;
//# sourceMappingURL=TabStateHelpers.js.map