// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import * as Common from '../../core/common/common.js';
import * as i18n from '../../core/i18n/i18n.js';
import * as Platform from '../../core/platform/platform.js';
import * as Root from '../../core/root/root.js';
import * as SDK from '../../core/sdk/sdk.js';
import * as TimelineModel from '../../models/timeline_model/timeline_model.js';
import * as TraceEngine from '../../models/trace/trace.js';
import type * as Protocol from '../../generated/protocol.js';

import {PerformanceModel} from './PerformanceModel.js';

const UIStrings = {
  /**
   * @description Text in Timeline Controller of the Performance panel.
   * A "CPU profile" is a recorded performance measurement how a specific target behaves.
   * "Target" in this context can mean a web page, service or normal worker.
   * "Not available" is used as there are multiple things that can go wrong, but we do not
   * know what exactly, just that the CPU profile was not correctly recorded.
   */
  cpuProfileForATargetIsNot: 'CPU profile for a target is not available.',
  /**
   *@description Text in Timeline Controller of the Performance panel indicating that the Performance Panel cannot
   * record a performance trace because the type of target (where possible types are page, service worker and shared
   * worker) doesn't support it.
   */
  tracingNotSupported: 'Performance trace recording not supported for this type of target',
};
const str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineController.ts', UIStrings);
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
export class TimelineController implements SDK.TargetManager.SDKModelObserver<SDK.CPUProfilerModel.CPUProfilerModel>,
                                           SDK.TracingManager.TracingManagerClient {
  private readonly target: SDK.Target.Target;
  private tracingManager: SDK.TracingManager.TracingManager|null;
  private performanceModel: PerformanceModel;
  private readonly client: Client;
  private readonly tracingModel: SDK.TracingModel.TracingModel;
  // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  private tracingCompleteCallback?: ((value: any) => void)|null;
  private profiling?: boolean;
  // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  private cpuProfiles?: Map<any, any>|null;

  constructor(target: SDK.Target.Target, client: Client) {
    this.target = target;
    this.tracingManager = target.model(SDK.TracingManager.TracingManager);
    this.performanceModel = new PerformanceModel();
    this.performanceModel.setMainTarget(target);
    this.client = client;
    this.tracingModel = new SDK.TracingModel.TracingModel();

    SDK.TargetManager.TargetManager.instance().observeModels(SDK.CPUProfilerModel.CPUProfilerModel, this);
  }

  dispose(): void {
    SDK.TargetManager.TargetManager.instance().unobserveModels(SDK.CPUProfilerModel.CPUProfilerModel, this);
  }

  mainTarget(): SDK.Target.Target {
    return this.target;
  }

  async startRecording(options: RecordingOptions): Promise<Protocol.ProtocolResponseWithError> {
    function disabledByDefault(category: string): string {
      return 'disabled-by-default-' + category;
    }

    // The following categories are also used in other tools, but this panel
    // offers the possibility of turning them off (see below).
    // 'disabled-by-default-devtools.screenshot'
    //   └ default: on, option: captureFilmStrip
    // 'disabled-by-default-devtools.timeline.invalidationTracking'
    //   └ default: off, experiment: timelineInvalidationTracking
    // 'disabled-by-default-v8.cpu_profiler'
    //   └ default: on, option: enableJSSampling
    const categoriesArray = [
      Root.Runtime.experiments.isEnabled('timelineShowAllEvents') ? '*' : '-*',
      TimelineModel.TimelineModel.TimelineModelImpl.Category.Console,
      TimelineModel.TimelineModel.TimelineModelImpl.Category.UserTiming,
      'devtools.timeline',
      disabledByDefault('devtools.timeline'),
      disabledByDefault('devtools.timeline.frame'),
      disabledByDefault('devtools.timeline.stack'),
      disabledByDefault('v8.compile'),
      disabledByDefault('v8.cpu_profiler.hires'),
      TimelineModel.TimelineModel.TimelineModelImpl.Category.Loading,
      disabledByDefault('lighthouse'),
      'v8.execute',
      'v8',
    ];

    if (Root.Runtime.experiments.isEnabled('timelineV8RuntimeCallStats') && options.enableJSSampling) {
      categoriesArray.push(disabledByDefault('v8.runtime_stats_sampling'));
    }
    if (options.enableJSSampling) {
      categoriesArray.push(disabledByDefault('v8.cpu_profiler'));
    }
    if (Root.Runtime.experiments.isEnabled('timelineInvalidationTracking')) {
      categoriesArray.push(disabledByDefault('devtools.timeline.invalidationTracking'));
    }
    if (options.capturePictures) {
      categoriesArray.push(
          disabledByDefault('devtools.timeline.layers'), disabledByDefault('devtools.timeline.picture'),
          disabledByDefault('blink.graphics_context_annotations'));
    }
    if (options.captureFilmStrip) {
      categoriesArray.push(disabledByDefault('devtools.screenshot'));
    }

    this.performanceModel.setRecordStartTime(Date.now());
    const response = await this.startRecordingWithCategories(categoriesArray.join(','));
    if (response.getError()) {
      await this.waitForTracingToStop(false);
      await SDK.TargetManager.TargetManager.instance().resumeAllTargets();
    }
    return response;
  }

  async stopRecording(): Promise<PerformanceModel> {
    if (this.tracingManager) {
      this.tracingManager.stop();
    }

    this.client.loadingStarted();
    await this.waitForTracingToStop(true);
    await this.allSourcesFinished();
    return this.performanceModel;
  }

  getPerformanceModel(): PerformanceModel {
    return this.performanceModel;
  }

  private async waitForTracingToStop(awaitTracingCompleteCallback: boolean): Promise<void> {
    const tracingStoppedPromises = [];
    if (this.tracingManager && awaitTracingCompleteCallback) {
      tracingStoppedPromises.push(new Promise(resolve => {
        this.tracingCompleteCallback = resolve;
      }));
    }
    tracingStoppedPromises.push(this.stopProfilingOnAllModels());

    await Promise.all(tracingStoppedPromises);
  }

  modelAdded(cpuProfilerModel: SDK.CPUProfilerModel.CPUProfilerModel): void {
    if (this.profiling) {
      void cpuProfilerModel.startRecording();
    }
  }

  modelRemoved(_cpuProfilerModel: SDK.CPUProfilerModel.CPUProfilerModel): void {
    // FIXME: We'd like to stop profiling on the target and retrieve a profile
    // but it's too late. Backend connection is closed.
  }

  private addCpuProfile(targetId: Protocol.Target.TargetID|'main', cpuProfile: Protocol.Profiler.Profile|null): void {
    if (!cpuProfile) {
      Common.Console.Console.instance().warn(i18nString(UIStrings.cpuProfileForATargetIsNot));
      return;
    }
    if (!this.cpuProfiles) {
      this.cpuProfiles = new Map();
    }
    this.cpuProfiles.set(targetId, cpuProfile);
  }

  private async stopProfilingOnAllModels(): Promise<void> {
    const models =
        this.profiling ? SDK.TargetManager.TargetManager.instance().models(SDK.CPUProfilerModel.CPUProfilerModel) : [];
    this.profiling = false;
    const promises = [];
    for (const model of models) {
      const targetId = model.target().id();
      const modelPromise = model.stopRecording().then(this.addCpuProfile.bind(this, targetId));
      promises.push(modelPromise);
    }
    await Promise.all(promises);
  }

  private async startRecordingWithCategories(categories: string): Promise<Protocol.ProtocolResponseWithError> {
    if (!this.tracingManager) {
      throw new Error(UIStrings.tracingNotSupported);
    }
    // There might be a significant delay in the beginning of timeline recording
    // caused by starting CPU profiler, that needs to traverse JS heap to collect
    // all the functions data.
    await SDK.TargetManager.TargetManager.instance().suspendAllTargets('performance-timeline');
    return this.tracingManager.start(this, categories, '');
  }

  traceEventsCollected(events: SDK.TracingManager.EventPayload[]): void {
    this.tracingModel.addEvents(events);
  }

  tracingComplete(): void {
    if (!this.tracingCompleteCallback) {
      return;
    }
    this.tracingCompleteCallback(undefined);
    this.tracingCompleteCallback = null;
  }

  private async allSourcesFinished(): Promise<void> {
    this.client.processingStarted();
    await this.finalizeTrace();
  }

  private async finalizeTrace(): Promise<void> {
    this.injectCpuProfileEvents();
    await SDK.TargetManager.TargetManager.instance().resumeAllTargets();
    this.tracingModel.tracingComplete();
    await this.client.loadingComplete(this.tracingModel, null);
    this.client.loadingCompleteForTest();
  }

  private injectCpuProfileEvent(pid: number, tid: number, cpuProfile: Protocol.Profiler.Profile|null): void {
    if (!cpuProfile) {
      return;
    }
    // TODO(crbug/1011811): This event type is not compatible with the SDK.TracingManager.EventPayload.
    // EventPayload requires many properties to be defined but it's not clear if they will have
    // any side effects.
    const cpuProfileEvent = ({
      cat: SDK.TracingModel.DevToolsMetadataEventCategory,
      ph: TraceEngine.Types.TraceEvents.Phase.INSTANT,
      ts: this.tracingModel.maximumRecordTime() * 1000,
      pid: pid,
      tid: tid,
      name: TimelineModel.TimelineModel.RecordType.CpuProfile,
      args: {data: {cpuProfile: cpuProfile}},
      // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
    } as any);
    this.tracingModel.addEvents([cpuProfileEvent]);
  }

  private buildTargetToProcessIdMap(): Map<string, number>|null {
    const metadataEventTypes = TimelineModel.TimelineModel.TimelineModelImpl.DevToolsMetadataEvent;
    const metadataEvents = this.tracingModel.devToolsMetadataEvents();
    const browserMetaEvent = metadataEvents.find(e => e.name === metadataEventTypes.TracingStartedInBrowser);
    if (!browserMetaEvent) {
      return null;
    }

    const pseudoPidToFrames = new Platform.MapUtilities.Multimap<string, string>();
    const targetIdToPid = new Map<string, number>();
    // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const frames: any[] = browserMetaEvent.args.data.frames;
    for (const frameInfo of frames) {
      targetIdToPid.set(frameInfo.frame, frameInfo.processId);
    }
    for (const event of metadataEvents) {
      const data = event.args.data;
      switch (event.name) {
        case metadataEventTypes.FrameCommittedInBrowser:
          if (data.processId) {
            targetIdToPid.set(data.frame, data.processId);
          } else {
            pseudoPidToFrames.set(data.processPseudoId, data.frame);
          }
          break;
        case metadataEventTypes.ProcessReadyInBrowser:
          for (const frame of pseudoPidToFrames.get(data.processPseudoId) || []) {
            targetIdToPid.set(frame, data.processId);
          }
          break;
      }
    }
    const mainFrame = frames.find(frame => !frame.parent);
    const mainRendererProcessId = mainFrame.processId;
    const mainProcess = this.tracingModel.getProcessById(mainRendererProcessId);
    if (mainProcess) {
      const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
      if (target) {
        targetIdToPid.set(target.id(), mainProcess.id());
      }
    }
    return targetIdToPid;
  }

  private injectCpuProfileEvents(): void {
    if (!this.cpuProfiles) {
      return;
    }

    const metadataEventTypes = TimelineModel.TimelineModel.TimelineModelImpl.DevToolsMetadataEvent;
    const metadataEvents = this.tracingModel.devToolsMetadataEvents();

    const targetIdToPid = this.buildTargetToProcessIdMap();
    if (targetIdToPid) {
      for (const [id, profile] of this.cpuProfiles) {
        const pid = targetIdToPid.get(id);
        if (!pid) {
          continue;
        }
        const process = this.tracingModel.getProcessById(pid);
        const thread =
            process && process.threadByName(TimelineModel.TimelineModel.TimelineModelImpl.RendererMainThreadName);
        if (thread) {
          this.injectCpuProfileEvent(pid, thread.id(), profile);
        }
      }
    } else {
      // Legacy backends support.
      const filteredEvents = metadataEvents.filter(event => event.name === metadataEventTypes.TracingStartedInPage);
      const mainMetaEvent = filteredEvents[filteredEvents.length - 1];
      if (mainMetaEvent) {
        const pid = mainMetaEvent.thread.process().id();
        if (this.tracingManager) {
          const mainCpuProfile = this.cpuProfiles.get(this.tracingManager.target().id());
          this.injectCpuProfileEvent(pid, mainMetaEvent.thread.id(), mainCpuProfile);
        }
      } else {
        // Or there was no tracing manager in the main target at all, in this case build the model full
        // of cpu profiles.
        let tid = 0;
        for (const pair of this.cpuProfiles) {
          const target = SDK.TargetManager.TargetManager.instance().targetById(pair[0]);
          const name = target && target.name();
          this.tracingModel.addEvents(
              TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.createFakeTraceFromCpuProfile(
                  pair[1], ++tid, /* injectPageEvent */ tid === 1, name));
        }
      }
    }

    const workerMetaEvents =
        metadataEvents.filter(event => event.name === metadataEventTypes.TracingSessionIdForWorker);
    for (const metaEvent of workerMetaEvents) {
      const workerId = metaEvent.args['data']['workerId'];
      const cpuProfile = this.cpuProfiles.get(workerId);
      this.injectCpuProfileEvent(metaEvent.thread.process().id(), metaEvent.args['data']['workerThreadId'], cpuProfile);
    }
    this.cpuProfiles = null;
  }

  tracingBufferUsage(usage: number): void {
    this.client.recordingProgress(usage);
  }

  eventsRetrievalProgress(progress: number): void {
    this.client.loadingProgress(progress);
  }
}

export interface Client {
  recordingProgress(usage: number): void;
  loadingStarted(): void;
  processingStarted(): void;
  loadingProgress(progress?: number): void;
  loadingComplete(
      tracingModel: SDK.TracingModel.TracingModel|null,
      exclusiveFilter: TimelineModel.TimelineModelFilter.TimelineModelFilter|null): Promise<void>;
  loadingCompleteForTest(): void;
}
export interface RecordingOptions {
  enableJSSampling?: boolean;
  capturePictures?: boolean;
  captureFilmStrip?: boolean;
}
