/**
 * DevExtreme (cjs/__internal/ui/m_defer_rendering.js)
 * Version: 24.1.7-build-24272-1937
 * Build date: Sat Sep 28 2024
 *
 * Copyright (c) 2012 - 2024 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
exports.default = void 0;
var _transition_executor = require("../../animation/transition_executor/transition_executor");
var _component_registrator = _interopRequireDefault(require("../../core/component_registrator"));
var _dom_adapter = _interopRequireDefault(require("../../core/dom_adapter"));
var _renderer = _interopRequireDefault(require("../../core/renderer"));
var _common = require("../../core/utils/common");
var _deferred = require("../../core/utils/deferred");
var _extend = require("../../core/utils/extend");
var _iterator = require("../../core/utils/iterator");
var _position = require("../../core/utils/position");
var _type = require("../../core/utils/type");
var _window = require("../../core/utils/window");
var _events_engine = _interopRequireDefault(require("../../events/core/events_engine"));
var _visibility_change = require("../../events/visibility_change");
var _load_indicator = _interopRequireDefault(require("../../ui/load_indicator"));
var _ui = _interopRequireDefault(require("../../ui/widget/ui.widget"));

function _interopRequireDefault(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    }
}
const window = (0, _window.getWindow)();
const WIDGET_CLASS = "dx-widget";
const DEFER_RENDERING_CLASS = "dx-deferrendering";
const PENDING_RENDERING_CLASS = "dx-pending-rendering";
const PENDING_RENDERING_MANUAL_CLASS = "dx-pending-rendering-manual";
const PENDING_RENDERING_ACTIVE_CLASS = "dx-pending-rendering-active";
const VISIBLE_WHILE_PENDING_RENDERING_CLASS = "dx-visible-while-pending-rendering";
const INVISIBLE_WHILE_PENDING_RENDERING_CLASS = "dx-invisible-while-pending-rendering";
const LOADINDICATOR_CONTAINER_CLASS = "dx-loadindicator-container";
const DEFER_RENDERING_LOADINDICATOR_CONTAINER_CLASS = "dx-deferrendering-loadindicator-container";
const DEFER_DEFER_RENDERING_LOAD_INDICATOR = "dx-deferrendering-load-indicator";
const ANONYMOUS_TEMPLATE_NAME = "content";
const ACTIONS = ["onRendered", "onShown"];
const DeferRendering = _ui.default.inherit({
    _getDefaultOptions() {
        return (0, _extend.extend)(this.callBase(), {
            showLoadIndicator: false,
            renderWhen: void 0,
            animation: void 0,
            staggerItemSelector: void 0,
            onRendered: null,
            onShown: null
        })
    },
    _getAnonymousTemplateName: () => "content",
    _init() {
        this.transitionExecutor = new _transition_executor.TransitionExecutor;
        this._initElement();
        this._initRender();
        this._$initialContent = this.$element().clone().contents();
        this._initActions();
        this.callBase()
    },
    _initElement() {
        this.$element().addClass("dx-deferrendering")
    },
    _initRender() {
        const that = this;
        const $element = this.$element();
        const renderWhen = this.option("renderWhen");
        const doRender = () => that._renderDeferredContent();
        if ((0, _type.isPromise)(renderWhen)) {
            (0, _deferred.fromPromise)(renderWhen).done(doRender)
        } else {
            $element.data("dx-render-delegate", doRender);
            if (void 0 === renderWhen) {
                $element.addClass("dx-pending-rendering-manual")
            }
        }
    },
    _initActions() {
        this._actions = {};
        (0, _iterator.each)(ACTIONS, ((_, action) => {
            this._actions[action] = this._createActionByOption(action) || _common.noop
        }))
    },
    _initMarkup() {
        this.callBase();
        if (!this._initContent) {
            this._initContent = this._renderContent;
            this._renderContent = () => {}
        }
        this._initContent()
    },
    _renderContentImpl() {
        this.$element().removeClass("dx-widget");
        this.$element().append(this._$initialContent);
        this._setLoadingState()
    },
    _renderDeferredContent() {
        const that = this;
        const $element = this.$element();
        const result = (0, _deferred.Deferred)();
        $element.removeClass("dx-pending-rendering-manual");
        $element.addClass("dx-pending-rendering-active");
        this._abortRenderTask();
        this._renderTask = (0, _common.executeAsync)((() => {
            that._renderImpl().done((() => {
                const shownArgs = {
                    element: $element
                };
                that._actions.onShown([shownArgs]);
                result.resolve(shownArgs)
            })).fail((function() {
                result.rejectWith(result, arguments)
            }))
        }));
        return result.promise()
    },
    _isElementInViewport(element) {
        const rect = (0, _position.getBoundingRect)(element);
        return rect.bottom >= 0 && rect.right >= 0 && rect.top <= (window.innerHeight || _dom_adapter.default.getDocumentElement().clientHeight) && rect.left <= (window.innerWidth || _dom_adapter.default.getDocumentElement().clientWidth)
    },
    _animate() {
        const that = this;
        const $element = this.$element();
        const animation = (0, _window.hasWindow)() && this.option("animation");
        const staggerItemSelector = this.option("staggerItemSelector");
        let animatePromise;
        that.transitionExecutor.stop();
        if (animation) {
            if (staggerItemSelector) {
                $element.find(staggerItemSelector).each((function() {
                    if (that._isElementInViewport(this)) {
                        that.transitionExecutor.enter((0, _renderer.default)(this), animation)
                    }
                }))
            } else {
                that.transitionExecutor.enter($element, animation)
            }
            animatePromise = that.transitionExecutor.start()
        } else {
            animatePromise = (0, _deferred.Deferred)().resolve().promise()
        }
        return animatePromise
    },
    _renderImpl() {
        const $element = this.$element();
        const renderedArgs = {
            element: $element
        };
        const contentTemplate = this._getTemplate(this._templateManager.anonymousTemplateName);
        if (contentTemplate) {
            contentTemplate.render({
                container: $element.empty(),
                noModel: true
            })
        }
        this._setRenderedState($element);
        _events_engine.default.trigger($element, "dxcontentrendered");
        this._actions.onRendered([renderedArgs]);
        this._isRendered = true;
        return this._animate()
    },
    _setLoadingState() {
        const $element = this.$element();
        const hasCustomLoadIndicator = !!$element.find(".dx-visible-while-pending-rendering").length;
        $element.addClass("dx-pending-rendering");
        if (!hasCustomLoadIndicator) {
            $element.children().addClass("dx-invisible-while-pending-rendering")
        }
        if (this.option("showLoadIndicator")) {
            this._showLoadIndicator($element)
        }
    },
    _showLoadIndicator($container) {
        this._$loadIndicator = new _load_indicator.default((0, _renderer.default)("<div>"), {
            visible: true
        }).$element().addClass("dx-deferrendering-load-indicator");
        (0, _renderer.default)("<div>").addClass("dx-loadindicator-container").addClass("dx-deferrendering-loadindicator-container").append(this._$loadIndicator).appendTo($container)
    },
    _setRenderedState() {
        const $element = this.$element();
        if (this._$loadIndicator) {
            this._$loadIndicator.remove()
        }
        $element.removeClass("dx-pending-rendering");
        $element.removeClass("dx-pending-rendering-active");
        (0, _visibility_change.triggerShownEvent)($element.children())
    },
    _optionChanged(args) {
        const {
            value: value
        } = args;
        const {
            previousValue: previousValue
        } = args;
        switch (args.name) {
            case "renderWhen":
                if (false === previousValue && true === value) {
                    this._renderOrAnimate()
                } else if (true === previousValue && false === value) {
                    this.transitionExecutor.stop();
                    this._setLoadingState()
                }
                break;
            case "showLoadIndicator":
            case "onRendered":
            case "onShown":
                break;
            default:
                this.callBase(args)
        }
    },
    _renderOrAnimate() {
        let result;
        if (this._isRendered) {
            this._setRenderedState();
            result = this._animate()
        } else {
            result = this._renderDeferredContent()
        }
        return result
    },
    renderContent() {
        return this._renderOrAnimate()
    },
    _abortRenderTask() {
        if (this._renderTask) {
            this._renderTask.abort();
            this._renderTask = void 0
        }
    },
    _dispose() {
        this.transitionExecutor.stop(true);
        this._abortRenderTask();
        this._actions = void 0;
        this._$initialContent = void 0;
        this.callBase()
    }
});
(0, _component_registrator.default)("dxDeferRendering", DeferRendering);
var _default = exports.default = DeferRendering;
