// Copyright (C) 2024 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import m from 'mithril';

import {
  Plugin,
  PluginContext,
  PluginContextTrace,
  PluginDescriptor,
} from '../../public';
import {duration, Span, Time, time, TimeSpan} from '../../base/time';
import {redrawModal, showModal} from '../../widgets/modal';
import {assertExists} from '../../base/logging';

const PLUGIN_ID = 'dev.perfetto.TimelineSync';
const DEFAULT_BROADCAST_CHANNEL = `${PLUGIN_ID}#broadcastChannel`;
const VIEWPORT_UPDATE_THROTTLE_TIME_FOR_SENDING_AFTER_RECEIVING_MS = 1_000;
const BIGINT_PRECISION_MULTIPLIER = 1_000_000_000n;
const ADVERTISE_PERIOD_MS = 10_000;
const DEFAULT_SESSION_ID = 1;
type ClientId = number;
type SessionId = number;

/**
 * Synchronizes the timeline of 2 or more perfetto traces.
 *
 * To trigger the sync, the command needs to be executed on one tab. It will
 * prompt a list of other tabs to keep in sync. Each tab advertise itself
 * on a BroadcastChannel upon trace load.
 *
 * This is able to sync between traces recorded at different times, even if
 * their durations don't match. The initial viewport bound for each trace is
 * selected when the enable command is called.
 */
class TimelineSync implements Plugin {
  private _chan?: BroadcastChannel;
  private _ctx?: PluginContextTrace;
  private _traceLoadTime = 0;
  // Attached to broadcast messages to allow other windows to remap viewports.
  private readonly _clientId: ClientId = Math.floor(Math.random() * 1_000_000);
  // Used to throttle sending updates after one has been received.
  private _lastReceivedUpdateMillis: number = 0;
  private _lastViewportBounds?: ViewportBounds;
  private _advertisedClients = new Map<ClientId, ClientInfo>();
  private _sessionId: SessionId = 0;
  // Used when the url passes ?dev.perfetto.TimelineSync:enable to auto-enable
  // timeline sync on trace load.
  private _sessionidFromUrl: SessionId = 0;

  // Contains the Viewport bounds of this window when it received the first sync
  // message from another one. This is used to re-scale timestamps, so that we
  // can sync 2 (or more!) traces with different length.
  // The initial viewport will be the one visible when the command is enabled.
  private _initialBoundsForSibling = new Map<
    ClientId,
    ViewportBoundsSnapshot
  >();

  onActivate(ctx: PluginContext): void {
    ctx.registerCommand({
      id: `dev.perfetto.SplitScreen#enableTimelineSync`,
      name: 'Enable timeline sync with other Perfetto UI tabs',
      callback: () => this.showTimelineSyncDialog(),
    });
    ctx.registerCommand({
      id: `dev.perfetto.SplitScreen#disableTimelineSync`,
      name: 'Disable timeline sync',
      callback: () => this.disableTimelineSync(this._sessionId),
    });

    // Start advertising this tab. This allows the command run in other
    // instances to discover us.
    this._chan = new BroadcastChannel(DEFAULT_BROADCAST_CHANNEL);
    this._chan.onmessage = this.onmessage.bind(this);
    document.addEventListener('visibilitychange', () => this.advertise());
    window.addEventListener('focus', () => this.advertise());
    setInterval(() => this.advertise(), ADVERTISE_PERIOD_MS);

    // Allow auto-enabling of timeline sync from the URI. The user can
    // optionally specify a session id, otherwise we just use a default one.
    const m = /dev.perfetto.TimelineSync:enable(=\d+)?/.exec(location.hash);
    if (m !== null) {
      this._sessionidFromUrl = m[1]
        ? parseInt(m[1].substring(1))
        : DEFAULT_SESSION_ID;
    }
  }

  onDeactivate(_: PluginContext) {
    this.disableTimelineSync(this._sessionId);
  }

  async onTraceLoad(ctx: PluginContextTrace) {
    this._ctx = ctx;
    this._traceLoadTime = Date.now();
    this.advertise();
    if (this._sessionidFromUrl !== 0) {
      this.enableTimelineSync(this._sessionidFromUrl);
    }
  }

  async onTraceUnload(_: PluginContextTrace) {
    this.disableTimelineSync(this._sessionId);
    this._ctx = undefined;
  }

  private advertise() {
    if (this._ctx === undefined) return; // Don't advertise if no trace loaded.
    this._chan?.postMessage({
      perfettoSync: {
        cmd: 'MSG_ADVERTISE',
        title: document.title,
        traceLoadTime: this._traceLoadTime,
      },
      clientId: this._clientId,
    } as SyncMessage);
  }

  private showTimelineSyncDialog() {
    let clientsSelect: HTMLSelectElement;

    // This nested function is invoked when the modal dialog buton is pressed.
    const doStartSession = () => {
      // Disable any prior session.
      this.disableTimelineSync(this._sessionId);
      const selectedClients = new Array<ClientId>();
      const sel = assertExists(clientsSelect).selectedOptions;
      for (let i = 0; i < sel.length; i++) {
        const clientId = parseInt(sel[i].value);
        if (!isNaN(clientId)) selectedClients.push(clientId);
      }
      selectedClients.push(this._clientId); // Always add ourselves.
      this._sessionId = Math.floor(Math.random() * 1_000_000);
      this._chan?.postMessage({
        perfettoSync: {
          cmd: 'MSG_SESSION_START',
          sessionId: this._sessionId,
          clients: selectedClients,
        },
        clientId: this._clientId,
      } as SyncMessage);
      this._initialBoundsForSibling.clear();
      this.scheduleViewportUpdateMessage();
    };

    // The function below is called on every mithril render pass. It's important
    // that this function re-computes the list of other clients on every pass.
    // The user will go to other tabs (which causes an advertise due to the
    // visibilitychange listener) and come back on here while the modal dialog
    // is still being displayed.
    const renderModalContents = (): m.Children => {
      const children: m.Children = [];
      this.purgeInactiveClients();
      const clients = Array.from(this._advertisedClients.entries());
      clients.sort((a, b) => b[1].traceLoadTime - a[1].traceLoadTime);
      for (const [clientId, info] of clients) {
        const opened = new Date(info.traceLoadTime).toLocaleTimeString();
        const attrs: {value: number; selected?: boolean} = {value: clientId};
        if (this._advertisedClients.size === 1) {
          attrs.selected = true;
        }
        children.push(m('option', attrs, `${info.title} (${opened})`));
      }
      return m(
        'div',
        {style: 'display: flex;  flex-direction: column;'},
        m(
          'div',
          'Select the perfetto UI tab(s) you want to keep in sync ' +
            '(Ctrl+Click to select many).',
        ),
        m(
          'div',
          "If you don't see the trace listed here, temporarily focus the " +
            'corresponding browser tab and then come back here.',
        ),
        m(
          'select[multiple=multiple][size=8]',
          {
            oncreate: (vnode: m.VnodeDOM) => {
              clientsSelect = vnode.dom as HTMLSelectElement;
            },
          },
          children,
        ),
      );
    };

    showModal({
      title: 'Synchronize timeline across several tabs',
      content: renderModalContents,
      buttons: [
        {
          primary: true,
          text: `Synchronize timelines`,
          action: doStartSession,
        },
      ],
    });
  }

  private enableTimelineSync(sessionId: SessionId) {
    if (sessionId === this._sessionId) return; // Already in this session id.
    this._sessionId = sessionId;
    this._initialBoundsForSibling.clear();
    this.scheduleViewportUpdateMessage();
  }

  private disableTimelineSync(sessionId: SessionId, skipMsg = false) {
    if (sessionId !== this._sessionId || this._sessionId === 0) return;

    if (!skipMsg) {
      this._chan?.postMessage({
        perfettoSync: {
          cmd: 'MSG_SESSION_STOP',
          sessionId: this._sessionId,
        },
        clientId: this._clientId,
      } as SyncMessage);
    }
    this._sessionId = 0;
    this._initialBoundsForSibling.clear();
  }

  private shouldThrottleViewportUpdates() {
    return (
      Date.now() - this._lastReceivedUpdateMillis <=
      VIEWPORT_UPDATE_THROTTLE_TIME_FOR_SENDING_AFTER_RECEIVING_MS
    );
  }

  private scheduleViewportUpdateMessage() {
    if (!this.active) return;
    const currentViewport = this.getCurrentViewportBounds();
    if (
      (!this._lastViewportBounds ||
        !this._lastViewportBounds.equals(currentViewport)) &&
      !this.shouldThrottleViewportUpdates()
    ) {
      this.sendViewportBounds(currentViewport);
      this._lastViewportBounds = currentViewport;
    }
    requestAnimationFrame(this.scheduleViewportUpdateMessage.bind(this));
  }

  private sendViewportBounds(viewportBounds: ViewportBounds) {
    this._chan?.postMessage({
      perfettoSync: {
        cmd: 'MSG_SET_VIEWPORT',
        sessionId: this._sessionId,
        viewportBounds,
      },
      clientId: this._clientId,
    } as SyncMessage);
  }

  private onmessage(msg: MessageEvent) {
    if (this._ctx === undefined) return; // Trace unloaded
    if (!('perfettoSync' in msg.data)) return;
    const msgData = msg.data as SyncMessage;
    const sync = msgData.perfettoSync;
    switch (sync.cmd) {
      case 'MSG_ADVERTISE':
        if (msgData.clientId !== this._clientId) {
          this._advertisedClients.set(msgData.clientId, {
            title: sync.title,
            traceLoadTime: sync.traceLoadTime,
            lastHeartbeat: Date.now(),
          });
          this.purgeInactiveClients();
          redrawModal();
        }
        break;
      case 'MSG_SESSION_START':
        if (sync.clients.includes(this._clientId)) {
          this.enableTimelineSync(sync.sessionId);
        }
        break;
      case 'MSG_SESSION_STOP':
        this.disableTimelineSync(sync.sessionId, /* skipMsg= */ true);
        break;
      case 'MSG_SET_VIEWPORT':
        if (sync.sessionId === this._sessionId) {
          this.onViewportSyncReceived(sync.viewportBounds, msgData.clientId);
        }
        break;
    }
  }

  private onViewportSyncReceived(
    requestViewBounds: ViewportBounds,
    source: ClientId,
  ) {
    if (!this.active) return;
    this.cacheSiblingInitialBoundIfNeeded(requestViewBounds, source);
    const remappedViewport = this.remapViewportBounds(
      requestViewBounds,
      source,
    );
    if (!this.getCurrentViewportBounds().equals(remappedViewport)) {
      this._lastReceivedUpdateMillis = Date.now();
      this._lastViewportBounds = remappedViewport;
      this._ctx?.timeline.setViewportTime(
        remappedViewport.start,
        remappedViewport.end,
      );
    }
  }

  private cacheSiblingInitialBoundIfNeeded(
    requestViewBounds: ViewportBounds,
    source: ClientId,
  ) {
    if (!this._initialBoundsForSibling.has(source)) {
      this._initialBoundsForSibling.set(source, {
        thisWindow: this.getCurrentViewportBounds(),
        otherWindow: requestViewBounds,
      });
    }
  }

  private remapViewportBounds(
    otherWindowBounds: ViewportBounds,
    source: ClientId,
  ): ViewportBounds {
    const initialSnapshot = this._initialBoundsForSibling.get(source)!;
    const otherInitial = initialSnapshot.otherWindow;
    const thisInitial = initialSnapshot.thisWindow;

    const [l, r] = this.percentageChange(
      otherInitial.start,
      otherInitial.end,
      otherWindowBounds.start,
      otherWindowBounds.end,
    );
    const thisWindowInitialLength = thisInitial.end - thisInitial.start;

    return new TimeSpan(
      Time.fromRaw(
        thisInitial.start +
          (thisWindowInitialLength * l) / BIGINT_PRECISION_MULTIPLIER,
      ),
      Time.fromRaw(
        thisInitial.start +
          (thisWindowInitialLength * r) / BIGINT_PRECISION_MULTIPLIER,
      ),
    );
  }

  /*
   * Returns the percentage (*1e9) of the starting point inside
   * [initialL, initialR] of [currentL, currentR].
   *
   * A few examples:
   * - If current == initial, the output is expected to be [0,1e9]
   * - If current  is inside the initial -> [>0, < 1e9]
   * - If current is completely outside initial to the right -> [>1e9, >>1e9].
   * - If current is completely outside initial to the left -> [<<0, <0]
   */
  private percentageChange(
    initialL: bigint,
    initialR: bigint,
    currentL: bigint,
    currentR: bigint,
  ): [bigint, bigint] {
    const initialW = initialR - initialL;
    const dtL = currentL - initialL;
    const dtR = currentR - initialL;
    return [this.divide(dtL, initialW), this.divide(dtR, initialW)];
  }

  private divide(a: bigint, b: bigint): bigint {
    // Let's not lose precision
    return (a * BIGINT_PRECISION_MULTIPLIER) / b;
  }

  private getCurrentViewportBounds(): ViewportBounds {
    return this._ctx!.timeline.viewport;
  }

  private purgeInactiveClients() {
    const now = Date.now();
    const TIMEOUT_MS = 30_000;
    for (const [clientId, info] of this._advertisedClients.entries()) {
      if (now - info.lastHeartbeat < TIMEOUT_MS) continue;
      this._advertisedClients.delete(clientId);
    }
  }

  private get active() {
    return this._sessionId !== 0;
  }
}

type ViewportBounds = Span<time, duration>;

interface ViewportBoundsSnapshot {
  thisWindow: ViewportBounds;
  otherWindow: ViewportBounds;
}

interface MsgSetViewport {
  cmd: 'MSG_SET_VIEWPORT';
  sessionId: SessionId;
  viewportBounds: ViewportBounds;
}

interface MsgAdvertise {
  cmd: 'MSG_ADVERTISE';
  title: string;
  traceLoadTime: number;
}

interface MsgSessionStart {
  cmd: 'MSG_SESSION_START';
  sessionId: SessionId;
  clients: ClientId[];
}

interface MsgSessionStop {
  cmd: 'MSG_SESSION_STOP';
  sessionId: SessionId;
}

// In case of new messages, they should be "or-ed" here.
type SyncMessages =
  | MsgSetViewport
  | MsgAdvertise
  | MsgSessionStart
  | MsgSessionStop;

interface SyncMessage {
  perfettoSync: SyncMessages;
  clientId: ClientId;
}

interface ClientInfo {
  title: string;
  lastHeartbeat: number; // Datetime.now() of the last MSG_ADVERTISE.
  traceLoadTime: number; // Datetime.now() of the onTraceLoad().
}

export const plugin: PluginDescriptor = {
  pluginId: PLUGIN_ID,
  plugin: TimelineSync,
};
