import*as Bindings from"../bindings/bindings.js";import*as Common from"../common/common.js";import*as Host from"../host/host.js";import*as i18n from"../i18n/i18n.js";import*as SDK from"../sdk/sdk.js";import*as TextUtils from"../text_utils/text_utils.js";import*as TimelineModel from"../timeline_model/timeline_model.js";const UIStrings={malformedTimelineDataUnknownJson:"Malformed timeline data: Unknown JSON format",malformedTimelineInputWrongJson:"Malformed timeline input, wrong JSON brackets balance",malformedTimelineDataS:"Malformed timeline data: {PH1}",legacyTimelineFormatIsNot:"Legacy Timeline format is not supported.",malformedCpuProfileFormat:"Malformed CPU profile format"},str_=i18n.i18n.registerUIStrings("timeline/TimelineLoader.js",UIStrings),i18nString=i18n.i18n.getLocalizedString.bind(void 0,str_);export class TimelineLoader{constructor(e){this._client=e,this._backingStorage=new Bindings.TempFile.TempFileBackingStorage,this._tracingModel=new SDK.TracingModel.TracingModel(this._backingStorage),this._canceledCallback=null,this._state=State.Initial,this._buffer="",this._firstRawChunk=!0,this._firstChunk=!0,this._loadedBytes=0,this._totalSize,this._jsonTokenizer=new TextUtils.TextUtils.BalancedJSONTokenizer(this._writeBalancedJSON.bind(this),!0)}static loadFromFile(e,t){const i=new TimelineLoader(t),n=new Bindings.FileUtils.ChunkedFileReader(e,TransferChunkLengthBytes);return i._canceledCallback=n.cancel.bind(n),i._totalSize=e.size,n.read(i).then((e=>{!e&&n.error()&&i._reportErrorAndCancelLoading(n.error().message)})),i}static loadFromEvents(e,t){const i=new TimelineLoader(t);return setTimeout((async()=>{t.loadingStarted();for(let n=0;n<e.length;n+=5e3){const r=e.slice(n,n+5e3);i._tracingModel.addEvents(r),t.loadingProgress((n+r.length)/e.length),await new Promise((e=>setTimeout(e)))}i.close()})),i}static loadFromURL(e,t){const i=new TimelineLoader(t);return Host.ResourceLoader.loadAsStream(e,null,i),i}cancel(){this._tracingModel=null,this._backingStorage.reset(),this._client&&(this._client.loadingComplete(null),this._client=null),this._canceledCallback&&this._canceledCallback()}write(e){if(!this._client)return Promise.resolve();if(this._loadedBytes+=e.length,this._firstRawChunk?this._client.loadingStarted():this._client.loadingProgress(this._totalSize?this._loadedBytes/this._totalSize:void 0),this._firstRawChunk=!1,this._state===State.Initial)if(e.startsWith('{"nodes":['))this._state=State.LoadingCPUProfileFormat;else if("{"===e[0])this._state=State.LookingForEvents;else{if("["!==e[0])return this._reportErrorAndCancelLoading(i18nString(UIStrings.malformedTimelineDataUnknownJson)),Promise.resolve();this._state=State.ReadingEvents}if(this._state===State.LoadingCPUProfileFormat)return this._buffer+=e,Promise.resolve();if(this._state===State.LookingForEvents){const t='"traceEvents":',i=this._buffer.length-t.length;this._buffer+=e;const n=this._buffer.indexOf(t,i);if(-1===n)return Promise.resolve();e=this._buffer.slice(n+t.length),this._state=State.ReadingEvents}return this._state!==State.ReadingEvents||this._jsonTokenizer.write(e)||(this._state=State.SkippingTail,this._firstChunk&&this._reportErrorAndCancelLoading(i18nString(UIStrings.malformedTimelineInputWrongJson))),Promise.resolve()}_writeBalancedJSON(e){let t,i=e+"]";if(!this._firstChunk){const e=i.indexOf(",");-1!==e&&(i=i.slice(e+1)),i="["+i}try{t=JSON.parse(i)}catch(n){return void this._reportErrorAndCancelLoading(i18nString(UIStrings.malformedTimelineDataS,{PH1:n.toString()}))}if(this._firstChunk&&(this._firstChunk=!1,this._looksLikeAppVersion(t[0])))this._reportErrorAndCancelLoading(i18nString(UIStrings.legacyTimelineFormatIsNot));else try{this._tracingModel.addEvents(t)}catch(n){this._reportErrorAndCancelLoading(i18nString(UIStrings.malformedTimelineDataS,{PH1:n.toString()}))}}_reportErrorAndCancelLoading(e){e&&Common.Console.Console.instance().error(e),this.cancel()}_looksLikeAppVersion(e){return"string"===typeof e&&-1!==e.indexOf("Chrome")}async close(){this._client&&(this._client.processingStarted(),setTimeout((()=>this._finalizeTrace()),0))}_finalizeTrace(){this._state===State.LoadingCPUProfileFormat&&(this._parseCPUProfileFormat(this._buffer),this._buffer=""),this._tracingModel.tracingComplete(),this._client.loadingComplete(this._tracingModel)}_parseCPUProfileFormat(e){let t;try{const i=JSON.parse(e);t=TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.buildTraceProfileFromCpuProfile(i,1,!0)}catch(i){return void this._reportErrorAndCancelLoading(i18nString(UIStrings.malformedCpuProfileFormat))}this._tracingModel.addEvents(t)}}export const TransferChunkLengthBytes=5e6;export class Client{loadingStarted(){}loadingProgress(e){}processingStarted(){}loadingComplete(e){}}export const State={Initial:Symbol("Initial"),LookingForEvents:Symbol("LookingForEvents"),ReadingEvents:Symbol("ReadingEvents"),SkippingTail:Symbol("SkippingTail"),LoadingCPUProfileFormat:Symbol("LoadingCPUProfileFormat")};