/*---------------------------------------------------------------------------------------------
 * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
 * See LICENSE.md in the project root for license terms and full copyright notice.
 *--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module ContentView
 */
import * as React from "react";
import { ViewportComponent } from "@itwin/imodel-components-react";
import { FillCentered } from "@itwin/core-react";
import { connectIModelConnectionAndViewState } from "../redux/connectIModel";
import { UiFramework } from "../UiFramework";
import { DefaultViewOverlay } from "./DefaultViewOverlay";
import { ViewportContentControl } from "./ViewportContentControl";
import { StandardRotationNavigationAidControl } from "../navigationaids/StandardRotationNavigationAid";
import { UiError } from "@itwin/appui-abstract";
import { useSelector } from "react-redux";
/** Viewport that is connected to the IModelConnection property in the Redux store. The application must set up the Redux store and include the FrameworkReducer.
 * @public
 */
export const IModelConnectedViewport = connectIModelConnectionAndViewState(null, null)(ViewportComponent);
/** View Overlay component -- exported for testing
 * @internal
 */
// istanbul ignore next
export function ViewOverlayHost({ viewport, featureOptions, userSuppliedOverlay, }) {
    const displayViewOverlay = useSelector((state) => {
        const frameworkState = state[UiFramework.frameworkStateKey];
        return frameworkState
            ? frameworkState.configurableUiState.viewOverlayDisplay
            : true;
    });
    if (!displayViewOverlay)
        return null;
    return userSuppliedOverlay ? (React.createElement(React.Fragment, null, userSuppliedOverlay(viewport))) : (React.createElement(DefaultViewOverlay, { viewport: viewport, featureOptions: featureOptions }));
}
/** iModel Viewport Control
 * @public
 */
// istanbul ignore next
export class IModelViewportControl extends ViewportContentControl {
    static get id() {
        return "UiFramework.IModelViewportControl";
    }
    constructor(info, _options) {
        super(info, _options);
        this._options = _options;
        this._featureOptions = {};
        /**
         * This is passed as a function to the ViewportComponent as the `viewState` prop in getImodelViewportReactElement().
         * It is called by ViewportComponent on a mount to resolve the viewState.
         */
        this._determineViewState = () => {
            let viewState;
            if (this.viewport && !this._alwaysUseSuppliedViewState)
                viewState = this.viewport.view;
            else if (this._viewState) {
                if (typeof this._viewState === "function")
                    viewState = this._viewState();
                else
                    viewState = this._viewState;
            }
            else
                throw new UiError(UiFramework.loggerCategory(this), "No ViewState could be determined");
            return viewState;
        };
        /** Get the default ViewOverlay unless parameter is set to not use it. May be override in an application specific sub-class  */
        this._getViewOverlay = (vp) => {
            return (React.createElement(ViewOverlayHost, { viewport: vp, featureOptions: this._featureOptions, userSuppliedOverlay: this._userSuppliedViewOverlay, "data-testid": "ViewOverlay" }));
        };
        if (_options.featureOptions)
            this._featureOptions = _options.featureOptions;
        this._alwaysUseSuppliedViewState =
            _options.alwaysUseSuppliedViewState ?? false;
        this._userSuppliedViewOverlay = _options.supplyViewOverlay;
        if (!_options.deferNodeInitialization)
            this.initializeReactNode();
    }
    initializeReactNode() {
        const options = this._options;
        if (options.viewState)
            this._viewState = options.viewState;
        const iModelConnection = typeof options.iModelConnection === "function"
            ? options.iModelConnection()
            : options.iModelConnection;
        if (this._viewState && iModelConnection) {
            /** Passing _determineViewState as a function reference; it is not called here. */
            this._reactNode = this.getImodelViewportReactElement(iModelConnection, this._determineViewState);
        }
        else {
            if (UiFramework.getIModelConnection() &&
                UiFramework.getDefaultViewState()) {
                this._reactNode = this.getImodelConnectedViewportReactElement();
            }
            else {
                this._reactNode = this.getNoContentReactElement(options);
                this.setIsReady();
            }
        }
    }
    getReactNode() {
        if (!React.isValidElement(this._reactNode) &&
            this._options.deferNodeInitialization)
            this.initializeReactNode();
        return this.getKeyedReactNode();
    }
    /** Get the React component that will contain the Viewport */
    getImodelConnectedViewportReactElement() {
        return (React.createElement(IModelConnectedViewport, { viewportRef: (v) => {
                this.viewport = v;
                // for convenience, if window defined bind viewport to window
                if (undefined !== window)
                    window.viewport = v;
                if (!UiFramework.frontstages.isLoading)
                    UiFramework.frontstages.activeFrontstageDef?.setActiveViewFromViewport(v);
            }, getViewOverlay: this._getViewOverlay }));
    }
    /** Get the React component that will contain the Viewport */
    getImodelViewportReactElement(iModelConnection, viewState) {
        return (React.createElement(ViewportComponent, { viewState: viewState, imodel: iModelConnection, controlId: this.controlId, viewportRef: (v) => {
                this.viewport = v;
                // for convenience, if window defined bind viewport to window
                if (undefined !== window)
                    window.viewport = v;
                if (!UiFramework.frontstages.isLoading)
                    UiFramework.frontstages.activeFrontstageDef?.setActiveViewFromViewport(v);
            }, getViewOverlay: this._getViewOverlay }));
    }
    /** Get the React component that will be shown when no iModel data is available */
    getNoContentReactElement(_options) {
        const noContent = UiFramework.translate("general.no-content");
        return React.createElement(FillCentered, null,
            " ",
            noContent,
            " ");
    }
    /** Get the React.Element for a ViewSelector change. */
    getReactElementForViewSelectorChange(iModelConnection, _unusedViewDefinitionId, viewState, _name) {
        return this.getImodelViewportReactElement(iModelConnection, viewState);
    }
    /** Get the NavigationAidControl associated with this ContentControl */
    get navigationAidControl() {
        if (this.viewport)
            return super.navigationAidControl;
        else
            return StandardRotationNavigationAidControl.navigationAidId;
    }
}
UiFramework.controls.register(IModelViewportControl.id, IModelViewportControl);
//# sourceMappingURL=IModelViewport.js.map