sap.ui.define([
], function() {
	"use strict";

	/**
	 * PreliminaryWrapper - Acts as a proxy wrapper before the real control is available.
	 *
	 * This wrapper is created when a control state wrapper is requested by ID and type,
	 * but the actual control instance doesn't exist yet (e.g., due to lazy loading on ObjectPage).
	 * It stores state operations and event handler registrations, then transfers them to the
	 * real wrapper once the control is assigned via setControl().
	 *
	 * @param {string} sId - The local ID of the control
	 * @param {string} sType - The type of the control (e.g., "SmartTable", "SmartChart")
	 * @param {function} fnCreateRealWrapper - Function to create the real wrapper, injected by factory
	 * @param {object} oController - The controller instance
	 * @param {object} mParams - Additional parameters to pass to the real wrapper constructor
	 * @returns {object} Preliminary wrapper object that will delegate to real wrapper once control is set
	 */
	function PreliminaryWrapper(sId, sType, fnCreateRealWrapper, oController, mParams) {
		var oLatestState;
		var oRealWrapper;
		var fnResolveRealWrapperReady;
		var oRealWrapperReadyPromise = new Promise(function(resolve) {
			fnResolveRealWrapperReady = resolve;
		});

		return {
			/**
			 * Get the current state. Returns stored state before control is set,
			 * delegates to real wrapper afterwards.
			 * @returns {object} The current state
			 */
			getState: function() {
				return oRealWrapper ? oRealWrapper.getState() : oLatestState;
			},

			/**
			 * Set the state. Stores state before control is set,
			 * delegates to real wrapper afterwards.
			 * @param {object} oState - The state to set
			 */
			setState: function(oState) {
				if (oRealWrapper) {
					oRealWrapper.setState(oState);
				} else {
					oLatestState = oState;
				}
			},

		/**
		 * Assign the actual control and create the real wrapper.
		 * This triggers the creation of the real wrapper, applies any stored state,
		 * and resolves the promise that queues event handler attachments.
		 * @param {sap.ui.core.Control} oControl - The control instance
		 */
		setControl: function(oControl) {
			// Create the real wrapper using injected function
			var oCreatedWrapper = fnCreateRealWrapper(oControl, sType, mParams);

			// Check if wrapper needs time to initialize
			var oWrapperReadyPromise = oCreatedWrapper.oReadyPromise || Promise.resolve();

			// Wait for wrapper to be ready before setting oRealWrapper
			oWrapperReadyPromise.then(function() {
				oRealWrapper = oCreatedWrapper;

				// Apply stored state if any
				if (oLatestState !== undefined) {
					oRealWrapper.setState(oLatestState);
				}

				// Resolve the promise - this triggers all queued attachStateChanged calls
				fnResolveRealWrapperReady(oRealWrapper);
			});
		},

		/**
		 * Attach a state change handler. Uses promise to queue attachment
		 * until the real wrapper is available and ready.
		 * @param {function} fnHandler - The event handler function
		 */
		attachStateChanged: function(fnHandler) {
			// Use promise to defer attachment until real wrapper is available and ready
			oRealWrapperReadyPromise.then(function(oWrapper) {
				oWrapper.attachStateChanged(fnHandler);
			});
		},

		/**
		 * Detach a state change handler. Forwards to real wrapper once available and ready.
		 * @param {function} fnHandler - The event handler function to detach
		 */
		detachStateChanged: function(fnHandler) {
			// Forward to real wrapper once available and ready
			oRealWrapperReadyPromise.then(function(oWrapper) {
				oWrapper.detachStateChanged(fnHandler);
			});
		},

			/**
			 * Get the local ID of the control.
			 * @returns {string} The local ID
			 */
			getLocalId: function() {
				return sId;
			},

			/**
			 * Check if the provided state matches the current state.
			 * @param {object} oState - The state to compare
			 * @returns {boolean} True if states match
			 */
			isCurrentState: function(oState) {
				return oRealWrapper ? oRealWrapper.isCurrentState(oState) :
					JSON.stringify(oState) === JSON.stringify(oLatestState);
			},

		/**
		 * Called after variant is initialized (for SmartTable/SmartChart wrappers).
		 * Delegates to real wrapper once control is set and ready.
		 * Note: When this is called, the control always exists (event fired by control),
		 * so the promise will already be resolved.
		 */
		onAfterVariantInitialise: function() {
			oRealWrapperReadyPromise.then(function(oWrapper) {
				if (oWrapper.onAfterVariantInitialise) {
					oWrapper.onAfterVariantInitialise();
				}
			});
		},

		/**
		 * Promise that resolves to the bVMConnection flag value once the real wrapper is ready.
		 * This indicates whether the control is connected to page-wide variant management.
		 */
		oVMConnectionPromise: oRealWrapperReadyPromise.then(function(oWrapper) {
			return oWrapper.bVMConnection;
		})
		};
	}

	return PreliminaryWrapper;
});
