// 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 {assertTrue} from '../base/logging';

export interface WorkspaceManager {
  // This is the same of ctx.workspace, exposed for consistency also here.
  readonly currentWorkspace: Workspace;
  readonly all: ReadonlyArray<Workspace>;
  createEmptyWorkspace(displayName: string): Workspace;
  switchWorkspace(workspace: Workspace): void;
}

let sessionUniqueIdCounter = 0;

/**
 * Creates a short ID which is unique to this instance of the UI.
 *
 * The advantage of using this over uuidv4() is that the ids produced are
 * significantly shorter, saving memory and making them more human
 * read/write-able which helps when debugging.
 *
 * Note: The ID range will reset every time the UI is restarted, so be careful
 * not rely on these IDs in any medium that can survive between UI instances.
 *
 * TODO(stevegolton): We could possibly move this into its own module and use it
 * everywhere where session-unique ids are required.
 */
function createSessionUniqueId(): string {
  // Return the counter in base36 (0-z) to keep the string as short as possible
  // but still human readable.
  return (sessionUniqueIdCounter++).toString(36);
}

/**
 * Describes generic parent track node functionality - i.e. any entity that can
 * contain child TrackNodes, providing methods to add, remove, and access child
 * nodes.
 *
 * This class is abstract because, while it can technically be instantiated on
 * its own (no abstract methods/properties), it can't and shouldn't be
 * instantiated anywhere in practice - all APIs require either a TrackNode or a
 * Workspace.
 *
 * Thus, it serves two purposes:
 * 1. Avoiding duplication between Workspace and TrackNode, which is an internal
 *    implementation detail of this module.
 * 2. Providing a typescript interface for a generic TrackNode container class,
 *    which otherwise you might have to achieve using `Workspace | TrackNode`
 *    which is uglier.
 *
 * If you find yourself using this as a Javascript class in external code, e.g.
 * `instance of TrackNodeContainer`, you're probably doing something wrong.
 */
export abstract class TrackNodeContainer {
  protected _children: Array<TrackNode> = [];
  protected readonly tracksById = new Map<string, TrackNode>();
  protected abstract fireOnChangeListener(): void;

  /**
   * True if this node has children, false otherwise.
   */
  get hasChildren(): boolean {
    return this._children.length > 0;
  }

  /**
   * The ordered list of children belonging to this node.
   */
  get children(): ReadonlyArray<TrackNode> {
    return this._children;
  }

  /**
   * Inserts a new child node considering it's sortOrder.
   *
   * The child will be added before the first child whose |sortOrder| is greater
   * than the child node's sort order, or at the end if one does not exist. If
   * |sortOrder| is omitted on either node in the comparison it is assumed to be
   * 0.
   *
   * @param child - The child node to add.
   */
  addChildInOrder(child: TrackNode): void {
    const insertPoint = this._children.find(
      (n) => (n.sortOrder ?? 0) > (child.sortOrder ?? 0),
    );
    if (insertPoint) {
      this.addChildBefore(child, insertPoint);
    } else {
      this.addChildLast(child);
    }
  }

  /**
   * Add a new child node at the start of the list of children.
   *
   * @param child The new child node to add.
   */
  addChildLast(child: TrackNode): void {
    this.adopt(child);
    this._children.push(child);
    this.fireOnChangeListener();
  }

  /**
   * Add a new child node at the end of the list of children.
   *
   * @param child The child node to add.
   */
  addChildFirst(child: TrackNode): void {
    this.adopt(child);
    this._children.unshift(child);
    this.fireOnChangeListener();
  }

  /**
   * Add a new child node before an existing child node.
   *
   * @param child The child node to add.
   * @param referenceNode An existing child node. The new node will be added
   * before this node.
   */
  addChildBefore(child: TrackNode, referenceNode: TrackNode): void {
    if (child === referenceNode) return;

    assertTrue(this.children.includes(referenceNode));

    this.adopt(child);

    const indexOfReference = this.children.indexOf(referenceNode);
    this._children.splice(indexOfReference, 0, child);
    this.fireOnChangeListener();
  }

  /**
   * Add a new child node after an existing child node.
   *
   * @param child The child node to add.
   * @param referenceNode An existing child node. The new node will be added
   * after this node.
   */
  addChildAfter(child: TrackNode, referenceNode: TrackNode): void {
    if (child === referenceNode) return;

    assertTrue(this.children.includes(referenceNode));

    this.adopt(child);

    const indexOfReference = this.children.indexOf(referenceNode);
    this._children.splice(indexOfReference + 1, 0, child);
    this.fireOnChangeListener();
  }

  /**
   * Remove a child node from this node.
   *
   * @param child The child node to remove.
   */
  removeChild(child: TrackNode): void {
    this._children = this.children.filter((x) => child !== x);
    child.parent = undefined;
    child.id && this.tracksById.delete(child.id);
    this.fireOnChangeListener();
  }

  /**
   * The flattened list of all descendent nodes.
   */
  get flatTracks(): ReadonlyArray<TrackNode> {
    return this.children.flatMap((node) => {
      return [node, ...node.flatTracks];
    });
  }

  /**
   * Remove all children from this node.
   */
  clear(): void {
    this._children = [];
    this.tracksById.clear();
    this.fireOnChangeListener();
  }

  /**
   * Find a track node by its id.
   *
   * Node: This is an O(N) operation where N is the depth of the target node.
   * I.e. this is more efficient than findTrackByURI().
   *
   * @param id The id of the node we want to find.
   * @returns The node or undefined if no such node exists.
   */
  getTrackById(id: string): TrackNode | undefined {
    const foundNode = this.tracksById.get(id);
    if (foundNode) {
      return foundNode;
    } else {
      // Recurse our children
      for (const child of this._children) {
        const foundNode = child.getTrackById(id);
        if (foundNode) return foundNode;
      }
    }
    return undefined;
  }

  private adopt(child: TrackNode): void {
    if (child.parent) {
      child.parent.removeChild(child);
    }
    child.parent = this;
    child.id && this.tracksById.set(child.id, child);
  }
}

export interface TrackNodeArgs {
  title: string;
  id: string;
  uri: string;
  headless: boolean;
  sortOrder: number;
  collapsed: boolean;
  isSummary: boolean;
  removable: boolean;
}

/**
 * A base class for any node with children (i.e. a group or a workspace).
 */
export class TrackNode extends TrackNodeContainer {
  // Immutable unique (within the workspace) ID of this track node. Used for
  // efficiently retrieving this node object from a workspace. Note: This is
  // different to |uri| which is used to reference a track to render on the
  // track. If this means nothing to you, don't bother using it.
  public readonly id: string;

  // Parent node - could be the workspace or another node.
  public parent?: TrackNodeContainer;

  // A human readable string for this track - displayed in the track shell.
  // TODO(stevegolton): Make this optional, so that if we implement a string for
  // this track then we can implement it here as well.
  public title: string;

  // The URI of the track content to display here.
  public uri?: string;

  // Optional sort order, which workspaces may or may not take advantage of for
  // sorting when displaying the workspace.
  public sortOrder?: number;

  // Don't show the header at all for this track, just show its un-nested
  // children. This is helpful to group together tracks that logically belong to
  // the same group (e.g. all ftrace cpu tracks) and ease the job of
  // sorting/grouping plugins.
  public headless: boolean;

  // If true, this track is to be used as a summary for its children. When the
  // group is expanded the track will become sticky to the top of the viewport
  // to provide context for the tracks within, and the content of this track
  // shall be omitted. It will also be squashed down to a smaller height to save
  // vertical space.
  public isSummary: boolean;

  // If true, this node will be removable by the user. It will show a little
  // close button in the track shell which the user can press to remove the
  // track from the workspace.
  public removable: boolean;

  protected _collapsed = true;

  constructor(args?: Partial<TrackNodeArgs>) {
    super();

    const {
      title = '',
      id = createSessionUniqueId(),
      uri,
      headless = false,
      sortOrder,
      collapsed = true,
      isSummary = false,
      removable = false,
    } = args ?? {};

    this.id = id;
    this.uri = uri;
    this.headless = headless;
    this.title = title;
    this.sortOrder = sortOrder;
    this.isSummary = isSummary;
    this._collapsed = collapsed;
    this.removable = removable;
  }

  /**
   * Remove this track from it's parent & unpin from the workspace if pinned.
   */
  remove(): void {
    this.workspace?.unpinTrack(this);
    this.parent?.removeChild(this);
  }

  /**
   * Add this track to the list of pinned tracks in its parent workspace.
   *
   * Has no effect if this track is not added to a workspace.
   */
  pin(): void {
    this.workspace?.pinTrack(this);
  }

  /**
   * Remove this track from the list of pinned tracks in its parent workspace.
   *
   * Has no effect if this track is not added to a workspace.
   */
  unpin(): void {
    this.workspace?.unpinTrack(this);
  }

  /**
   * Returns true if this node is added to a workspace as is in the pinned track
   * list of that workspace.
   */
  get isPinned(): boolean {
    return Boolean(this.workspace?.hasPinnedTrack(this));
  }

  /**
   * Find the closest visible ancestor TrackNode.
   *
   * Given the path from the root workspace to this node, find the fist one,
   * starting from the root, which is collapsed. This will be, from the user's
   * point of view, the closest ancestor of this node.
   *
   * Returns undefined if this node is actually visible.
   *
   * TODO(stevegolton): Should it return itself in this case?
   */
  findClosestVisibleAncestor(): TrackNode {
    // Build a path from the root workspace to this node
    const path: TrackNode[] = [];
    let node = this.parent;
    while (node && node instanceof TrackNode) {
      path.unshift(node);
      node = node.parent;
    }

    // Find the first collapsed track in the path starting from the root. This
    // is effectively the closest we can get to this node without expanding any
    // groups.
    return path.find((node) => node.collapsed) ?? this;
  }

  /**
   * Expand all ancestor nodes.
   */
  reveal(): void {
    let parent = this.parent;
    while (parent && parent instanceof TrackNode) {
      parent.expand();
      parent = parent.parent;
    }
  }

  /**
   * Find this node's root node - this may be a workspace or another node.
   */
  get rootNode(): TrackNodeContainer | undefined {
    // Travel upwards through the tree to find the root node.
    let parent: TrackNodeContainer | undefined = this;
    while (parent && parent instanceof TrackNode) {
      parent = parent.parent;
    }
    return parent;
  }

  /**
   * Find this node's parent workspace if it is attached to one.
   */
  get workspace(): Workspace | undefined {
    // Find the root node and return it if it's a Workspace instance
    const rootNode = this.rootNode;
    if (rootNode instanceof Workspace) {
      return rootNode;
    }
    return undefined;
  }

  /**
   * Mark this node as un-collapsed, indicating its children should be rendered.
   */
  expand(): void {
    this._collapsed = false;
    this.fireOnChangeListener();
  }

  /**
   * Mark this node as collapsed, indicating its children should not be
   * rendered.
   */
  collapse(): void {
    this._collapsed = true;
    this.fireOnChangeListener();
  }

  /**
   * Toggle the collapsed state.
   */
  toggleCollapsed(): void {
    this._collapsed = !this._collapsed;
    this.fireOnChangeListener();
  }

  /**
   * Whether this node is collapsed, indicating its children should be rendered.
   */
  get collapsed(): boolean {
    return this._collapsed;
  }

  /**
   * Whether this node is expanded - i.e. not collapsed, indicating its children
   * should be rendered.
   */
  get expanded(): boolean {
    return !this._collapsed;
  }

  /**
   * Returns the list of titles representing the full path from the root node to
   * the current node. This path consists only of node titles, workspaces are
   * omitted.
   */
  get fullPath(): ReadonlyArray<string> {
    let fullPath = [this.title];
    let parent = this.parent;
    while (parent && parent instanceof TrackNode) {
      // Ignore headless containers as they don't appear in the tree...
      if (!parent.headless) {
        fullPath = [parent.title, ...fullPath];
      }
      parent = parent.parent;
    }
    return fullPath;
  }

  protected override fireOnChangeListener(): void {
    this.workspace?.onchange(this.workspace);
  }
}

/**
 * Defines a workspace containing a track tree and a pinned area.
 */
export class Workspace extends TrackNodeContainer {
  public title = '<untitled-workspace>';
  public readonly id: string;
  onchange: (w: Workspace) => void = () => {};

  // Dummy node to contain the pinned tracks
  public readonly pinnedRoot = new TrackNode();

  get pinnedTracks(): ReadonlyArray<TrackNode> {
    return this.pinnedRoot.children;
  }

  constructor() {
    super();
    this.id = createSessionUniqueId();
    this.pinnedRoot.parent = this;
  }

  /**
   * Reset the entire workspace including the pinned tracks.
   */
  override clear(): void {
    super.clear();
    this.pinnedRoot.clear();
  }

  /**
   * Adds a track node to this workspace's pinned area.
   */
  pinTrack(track: TrackNode): void {
    // Make a lightweight clone of this track - just the uri and the title.
    const cloned = new TrackNode({
      uri: track.uri,
      title: track.title,
      removable: track.removable,
    });
    this.pinnedRoot.addChildLast(cloned);
  }

  /**
   * Removes a track node from this workspace's pinned area.
   */
  unpinTrack(track: TrackNode): void {
    const foundNode = this.pinnedRoot.children.find((t) => t.uri === track.uri);
    if (foundNode) {
      this.pinnedRoot.removeChild(foundNode);
    }
  }

  /**
   * Check if this workspace has a pinned track with the same URI as |track|.
   */
  hasPinnedTrack(track: TrackNode): boolean {
    return this.pinnedTracks.some((p) => p.uri === track.uri);
  }

  /**
   * Find a track node via its URI.
   *
   * Note: This in an O(N) operation where N is the number of nodes in the
   * workspace.
   *
   * @param uri The uri of the track to find.
   * @returns A reference to the track node if it exists in this workspace,
   * otherwise undefined.
   */
  findTrackByUri(uri: string): TrackNode | undefined {
    return this.flatTracks.find((t) => t.uri === uri);
  }

  /**
   * Find a track by ID, also searching pinned tracks.
   */
  override getTrackById(id: string): TrackNode | undefined {
    // Also search the pinned tracks
    return this.pinnedRoot.getTrackById(id) || super.getTrackById(id);
  }

  protected override fireOnChangeListener(): void {
    this.onchange(this);
  }
}
