import{assert}from"./assert.js";import{CDPSessionEmittedEvents}from"./Connection.js";import{TimeoutError}from"./Errors.js";import{FrameManagerEmittedEvents}from"./FrameManager.js";import{helper}from"./helper.js";import{NetworkManagerEmittedEvents}from"./NetworkManager.js";const puppeteerToProtocolLifecycle=new Map([["load","load"],["domcontentloaded","DOMContentLoaded"],["networkidle0","networkIdle"],["networkidle2","networkAlmostIdle"]]);export class LifecycleWatcher{constructor(e,t,i,a){Array.isArray(i)?i=i.slice():"string"===typeof i&&(i=[i]),this._expectedLifecycle=i.map((e=>{const t=puppeteerToProtocolLifecycle.get(e);return assert(t,"Unknown value for options.waitUntil: "+e),t})),this._frameManager=e,this._frame=t,this._initialLoaderId=t._loaderId,this._timeout=a,this._navigationRequest=null,this._eventListeners=[helper.addEventListener(e._client,CDPSessionEmittedEvents.Disconnected,(()=>this._terminate(new Error("Navigation failed because browser has disconnected!")))),helper.addEventListener(this._frameManager,FrameManagerEmittedEvents.LifecycleEvent,this._checkLifecycleComplete.bind(this)),helper.addEventListener(this._frameManager,FrameManagerEmittedEvents.FrameNavigatedWithinDocument,this._navigatedWithinDocument.bind(this)),helper.addEventListener(this._frameManager,FrameManagerEmittedEvents.FrameDetached,this._onFrameDetached.bind(this)),helper.addEventListener(this._frameManager.networkManager(),NetworkManagerEmittedEvents.Request,this._onRequest.bind(this))],this._sameDocumentNavigationPromise=new Promise((e=>{this._sameDocumentNavigationCompleteCallback=e})),this._lifecyclePromise=new Promise((e=>{this._lifecycleCallback=e})),this._newDocumentNavigationPromise=new Promise((e=>{this._newDocumentNavigationCompleteCallback=e})),this._timeoutPromise=this._createTimeoutPromise(),this._terminationPromise=new Promise((e=>{this._terminationCallback=e})),this._checkLifecycleComplete()}_onRequest(e){e.frame()===this._frame&&e.isNavigationRequest()&&(this._navigationRequest=e)}_onFrameDetached(e){this._frame!==e?this._checkLifecycleComplete():this._terminationCallback.call(null,new Error("Navigating frame was detached"))}navigationResponse(){return this._navigationRequest?this._navigationRequest.response():null}_terminate(e){this._terminationCallback.call(null,e)}sameDocumentNavigationPromise(){return this._sameDocumentNavigationPromise}newDocumentNavigationPromise(){return this._newDocumentNavigationPromise}lifecyclePromise(){return this._lifecyclePromise}timeoutOrTerminationPromise(){return Promise.race([this._timeoutPromise,this._terminationPromise])}_createTimeoutPromise(){if(!this._timeout)return new Promise((()=>{}));const e="Navigation timeout of "+this._timeout+" ms exceeded";return new Promise((e=>this._maximumTimer=setTimeout(e,this._timeout))).then((()=>new TimeoutError(e)))}_navigatedWithinDocument(e){e===this._frame&&(this._hasSameDocumentNavigation=!0,this._checkLifecycleComplete())}_checkLifecycleComplete(){(function e(t,i){for(const a of i)if(!t._lifecycleEvents.has(a))return!1;for(const a of t.childFrames())if(!e(a,i))return!1;return!0})(this._frame,this._expectedLifecycle)&&(this._lifecycleCallback(),(this._frame._loaderId!==this._initialLoaderId||this._hasSameDocumentNavigation)&&(this._hasSameDocumentNavigation&&this._sameDocumentNavigationCompleteCallback(),this._frame._loaderId!==this._initialLoaderId&&this._newDocumentNavigationCompleteCallback()))}dispose(){helper.removeEventListeners(this._eventListeners),clearTimeout(this._maximumTimer)}}