// Copyright (C) 2022 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 {v4 as uuidv4} from 'uuid';

import {Disposable, Trash} from '../base/disposable';
import {Registry} from '../base/registry';
import {Span, duration, time} from '../base/time';
import {globals} from '../frontend/globals';
import {
  Command,
  DetailsPanel,
  EngineProxy,
  MetricVisualisation,
  Migrate,
  Plugin,
  PluginContext,
  PluginContextTrace,
  PluginDescriptor,
  PrimaryTrackSortKey,
  Store,
  TabDescriptor,
  TrackDescriptor,
  TrackPredicate,
  GroupPredicate,
  TrackRef,
} from '../public';
import {Engine} from '../trace_processor/engine';

import {Actions} from './actions';
import {SCROLLING_TRACK_GROUP} from './state';
import {addQueryResultsTab} from '../frontend/query_result_tab';
import {Flag, featureFlags} from '../core/feature_flags';
import {assertExists} from '../base/logging';
import {raf} from '../core/raf_scheduler';
import {defaultPlugins} from '../core/default_plugins';
import {HighPrecisionTimeSpan} from './high_precision_time';

// Every plugin gets its own PluginContext. This is how we keep track
// what each plugin is doing and how we can blame issues on particular
// plugins.
// The PluginContext exists for the whole duration a plugin is active.
export class PluginContextImpl implements PluginContext, Disposable {
  private trash = new Trash();
  private alive = true;

  readonly sidebar = {
    hide() {
      globals.dispatch(
        Actions.setSidebar({
          visible: false,
        }),
      );
    },
    show() {
      globals.dispatch(
        Actions.setSidebar({
          visible: true,
        }),
      );
    },
    isVisible() {
      return globals.state.sidebarVisible;
    },
  };

  registerCommand(cmd: Command): void {
    // Silently ignore if context is dead.
    if (!this.alive) return;

    const disposable = globals.commandManager.registerCommand(cmd);
    this.trash.add(disposable);
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  runCommand(id: string, ...args: any[]): any {
    return globals.commandManager.runCommand(id, ...args);
  }

  constructor(readonly pluginId: string) {}

  dispose(): void {
    this.trash.dispose();
    this.alive = false;
  }
}

// This PluginContextTrace implementation provides the plugin access to trace
// related resources, such as the engine and the store.
// The PluginContextTrace exists for the whole duration a plugin is active AND a
// trace is loaded.
class PluginContextTraceImpl implements PluginContextTrace, Disposable {
  private trash = new Trash();
  private alive = true;

  constructor(private ctx: PluginContext, readonly engine: EngineProxy) {
    this.trash.add(engine);
  }

  registerCommand(cmd: Command): void {
    // Silently ignore if context is dead.
    if (!this.alive) return;

    const dispose = globals.commandManager.registerCommand(cmd);
    this.trash.add(dispose);
  }

  registerTrack(trackDesc: TrackDescriptor): void {
    // Silently ignore if context is dead.
    if (!this.alive) return;

    const dispose = globals.trackManager.registerTrack(trackDesc);
    this.trash.add(dispose);
  }

  addDefaultTrack(track: TrackRef): void {
    // Silently ignore if context is dead.
    if (!this.alive) return;

    const dispose = globals.trackManager.addPotentialTrack(track);
    this.trash.add(dispose);
  }

  registerStaticTrack(track: TrackDescriptor & TrackRef): void {
    this.registerTrack(track);
    this.addDefaultTrack(track);
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  runCommand(id: string, ...args: any[]): any {
    return this.ctx.runCommand(id, ...args);
  }

  registerTab(desc: TabDescriptor): void {
    if (!this.alive) return;

    const unregister = globals.tabManager.registerTab(desc);
    this.trash.add(unregister);
  }

  addDefaultTab(uri: string): void {
    const remove = globals.tabManager.addDefaultTab(uri);
    this.trash.add(remove);
  }

  registerDetailsPanel(section: DetailsPanel): void {
    if (!this.alive) return;

    const tabMan = globals.tabManager;
    const unregister = tabMan.registerDetailsPanel(section);
    this.trash.add(unregister);
  }

  get sidebar() {
    return this.ctx.sidebar;
  }

  readonly tabs = {
    openQuery: (query: string, title: string) => {
      addQueryResultsTab({query, title});
    },

    showTab(uri: string): void {
      globals.dispatch(Actions.showTab({uri}));
    },

    hideTab(uri: string): void {
      globals.dispatch(Actions.hideTab({uri}));
    },
  };

  get pluginId(): string {
    return this.ctx.pluginId;
  }

  readonly timeline = {
    // Add a new track to the timeline, returning its key.
    addTrack(uri: string, displayName: string, params?: unknown): string {
      const trackKey = uuidv4();
      globals.dispatch(
        Actions.addTrack({
          key: trackKey,
          uri,
          name: displayName,
          params,
          trackSortKey: PrimaryTrackSortKey.ORDINARY_TRACK,
          trackGroup: SCROLLING_TRACK_GROUP,
        }),
      );
      return trackKey;
    },

    removeTrack(key: string): void {
      globals.dispatch(Actions.removeTracks({trackKeys: [key]}));
    },

    pinTrack(key: string) {
      if (!isPinned(key)) {
        globals.dispatch(Actions.toggleTrackPinned({trackKey: key}));
      }
    },

    unpinTrack(key: string) {
      if (isPinned(key)) {
        globals.dispatch(Actions.toggleTrackPinned({trackKey: key}));
      }
    },

    pinTracksByPredicate(predicate: TrackPredicate) {
      const tracks = Object.values(globals.state.tracks);
      for (const track of tracks) {
        const tags = {
          name: track.name,
        };
        if (predicate(tags) && !isPinned(track.key)) {
          globals.dispatch(
            Actions.toggleTrackPinned({
              trackKey: track.key,
            }),
          );
        }
      }
    },

    unpinTracksByPredicate(predicate: TrackPredicate) {
      const tracks = Object.values(globals.state.tracks);
      for (const track of tracks) {
        const tags = {
          name: track.name,
        };
        if (predicate(tags) && isPinned(track.key)) {
          globals.dispatch(
            Actions.toggleTrackPinned({
              trackKey: track.key,
            }),
          );
        }
      }
    },

    removeTracksByPredicate(predicate: TrackPredicate) {
      const trackKeysToRemove = Object.values(globals.state.tracks)
        .filter((track) => {
          const tags = {
            name: track.name,
          };
          return predicate(tags);
        })
        .map((trackState) => trackState.key);

      globals.dispatch(Actions.removeTracks({trackKeys: trackKeysToRemove}));
    },

    expandGroupsByPredicate(predicate: GroupPredicate) {
      const groups = globals.state.trackGroups;
      const groupsToExpand = Object.values(groups)
        .filter((group) => group.collapsed)
        .filter((group) => {
          const ref = {
            displayName: group.name,
            collapsed: group.collapsed,
          };
          return predicate(ref);
        })
        .map((group) => group.id);

      for (const trackGroupId of groupsToExpand) {
        globals.dispatch(Actions.toggleTrackGroupCollapsed({trackGroupId}));
      }
    },

    collapseGroupsByPredicate(predicate: GroupPredicate) {
      const groups = globals.state.trackGroups;
      const groupsToCollapse = Object.values(groups)
        .filter((group) => !group.collapsed)
        .filter((group) => {
          const ref = {
            displayName: group.name,
            collapsed: group.collapsed,
          };
          return predicate(ref);
        })
        .map((group) => group.id);

      for (const trackGroupId of groupsToCollapse) {
        globals.dispatch(Actions.toggleTrackGroupCollapsed({trackGroupId}));
      }
    },

    get tracks(): TrackRef[] {
      const tracks = Object.values(globals.state.tracks);
      const pinnedTracks = globals.state.pinnedTracks;
      const groups = globals.state.trackGroups;
      return tracks.map((trackState) => {
        const group = trackState.trackGroup
          ? groups[trackState.trackGroup]
          : undefined;
        return {
          displayName: trackState.name,
          uri: trackState.uri,
          params: trackState.params,
          key: trackState.key,
          groupName: group?.name,
          isPinned: pinnedTracks.includes(trackState.key),
        };
      });
    },

    panToTimestamp(ts: time): void {
      globals.panToTimestamp(ts);
    },

    setViewportTime(start: time, end: time): void {
      const interval = HighPrecisionTimeSpan.fromTime(start, end);
      globals.timeline.updateVisibleTime(interval);
    },

    get viewport(): Span<time, duration> {
      return globals.timeline.visibleTimeSpan;
    },
  };

  dispose(): void {
    this.trash.dispose();
    this.alive = false;
  }

  mountStore<T>(migrate: Migrate<T>): Store<T> {
    return globals.store.createSubStore(['plugins', this.pluginId], migrate);
  }

  readonly trace = {
    get span(): Span<time, duration> {
      return globals.stateTraceTimeTP();
    },
  };
}

function isPinned(trackId: string): boolean {
  return globals.state.pinnedTracks.includes(trackId);
}

// 'Static' registry of all known plugins.
export class PluginRegistry extends Registry<PluginDescriptor> {
  constructor() {
    super((info) => info.pluginId);
  }
}

export interface PluginDetails {
  plugin: Plugin;
  context: PluginContext & Disposable;
  traceContext?: PluginContextTraceImpl;
  previousOnTraceLoadTimeMillis?: number;
}

function makePlugin(info: PluginDescriptor): Plugin {
  const {plugin} = info;

  // Class refs are functions, concrete plugins are not
  if (typeof plugin === 'function') {
    const PluginClass = plugin;
    return new PluginClass();
  } else {
    return plugin;
  }
}

export class PluginManager {
  private registry: PluginRegistry;
  private _plugins: Map<string, PluginDetails>;
  private engine?: Engine;
  private flags = new Map<string, Flag>();

  constructor(registry: PluginRegistry) {
    this.registry = registry;
    this._plugins = new Map();
  }

  get plugins(): Map<string, PluginDetails> {
    return this._plugins;
  }

  // Must only be called once on startup
  async initialize(): Promise<void> {
    for (const plugin of pluginRegistry.values()) {
      const id = `plugin_${plugin.pluginId}`;
      const name = `Plugin: ${plugin.pluginId}`;
      const flag = featureFlags.register({
        id,
        name,
        description: `Overrides '${id}' plugin.`,
        defaultValue: defaultPlugins.includes(plugin.pluginId),
      });
      this.flags.set(plugin.pluginId, flag);
      if (flag.get()) {
        await this.activatePlugin(plugin.pluginId);
      }
    }
  }

  /**
   * Enable plugin flag - i.e. configure a plugin to start on boot.
   * @param id The ID of the plugin.
   * @param now Optional: If true, also activate the plugin now.
   */
  async enablePlugin(id: string, now?: boolean): Promise<void> {
    const flag = this.flags.get(id);
    if (flag) {
      flag.set(true);
    }
    now && (await this.activatePlugin(id));
  }

  /**
   * Disable plugin flag - i.e. configure a plugin not to start on boot.
   * @param id The ID of the plugin.
   * @param now Optional: If true, also deactivate the plugin now.
   */
  async disablePlugin(id: string, now?: boolean): Promise<void> {
    const flag = this.flags.get(id);
    if (flag) {
      flag.set(false);
    }
    now && (await this.deactivatePlugin(id));
  }

  /**
   * Start a plugin just for this session. This setting is not persisted.
   * @param id The ID of the plugin to start.
   */
  async activatePlugin(id: string): Promise<void> {
    if (this.isActive(id)) {
      return;
    }

    const pluginInfo = this.registry.get(id);
    const plugin = makePlugin(pluginInfo);

    const context = new PluginContextImpl(id);

    plugin.onActivate?.(context);

    const pluginDetails: PluginDetails = {
      plugin,
      context,
    };

    // If a trace is already loaded when plugin is activated, make sure to
    // call onTraceLoad().
    if (this.engine) {
      await doPluginTraceLoad(pluginDetails, this.engine, id);
    }

    this._plugins.set(id, pluginDetails);

    raf.scheduleFullRedraw();
  }

  /**
   * Stop a plugin just for this session. This setting is not persisted.
   * @param id The ID of the plugin to stop.
   */
  async deactivatePlugin(id: string): Promise<void> {
    const pluginDetails = this.getPluginContext(id);
    if (pluginDetails === undefined) {
      return;
    }
    const {context, plugin} = pluginDetails;

    await doPluginTraceUnload(pluginDetails);

    plugin.onDeactivate && plugin.onDeactivate(context);
    context.dispose();

    this._plugins.delete(id);

    raf.scheduleFullRedraw();
  }

  /**
   * Restore all plugins enable/disabled flags to their default values.
   * @param now Optional: Also activates/deactivates plugins to match flag
   * settings.
   */
  async restoreDefaults(now?: boolean): Promise<void> {
    for (const plugin of pluginRegistry.values()) {
      const pluginId = plugin.pluginId;
      const flag = assertExists(this.flags.get(pluginId));
      flag.reset();
      if (now) {
        if (flag.get()) {
          await this.activatePlugin(plugin.pluginId);
        } else {
          await this.deactivatePlugin(plugin.pluginId);
        }
      }
    }
  }

  isActive(pluginId: string): boolean {
    return this.getPluginContext(pluginId) !== undefined;
  }

  isEnabled(pluginId: string): boolean {
    return Boolean(this.flags.get(pluginId)?.get());
  }

  getPluginContext(pluginId: string): PluginDetails | undefined {
    return this._plugins.get(pluginId);
  }

  async onTraceLoad(
    engine: Engine,
    beforeEach?: (id: string) => void,
  ): Promise<void> {
    this.engine = engine;
    const plugins = Array.from(this._plugins.entries());
    // Awaiting all plugins in parallel will skew timing data as later plugins
    // will spend most of their time waiting for earlier plugins to load.
    // Running in parallel will have very little performance benefit assuming
    // most plugins use the same engine, which can only process one query at a
    // time.
    for (const [id, pluginDetails] of plugins) {
      beforeEach?.(id);
      await doPluginTraceLoad(pluginDetails, engine, id);
    }
  }

  onTraceClose() {
    for (const pluginDetails of this._plugins.values()) {
      doPluginTraceUnload(pluginDetails);
    }
    this.engine = undefined;
  }

  metricVisualisations(): MetricVisualisation[] {
    return Array.from(this._plugins.values()).flatMap((ctx) => {
      const tracePlugin = ctx.plugin;
      if (tracePlugin.metricVisualisations) {
        return tracePlugin.metricVisualisations(ctx.context);
      } else {
        return [];
      }
    });
  }
}

async function doPluginTraceLoad(
  pluginDetails: PluginDetails,
  engine: Engine,
  pluginId: string,
): Promise<void> {
  const {plugin, context} = pluginDetails;

  const engineProxy = engine.getProxy(pluginId);

  const traceCtx = new PluginContextTraceImpl(context, engineProxy);
  pluginDetails.traceContext = traceCtx;

  const startTime = performance.now();
  const result = await Promise.resolve(plugin.onTraceLoad?.(traceCtx));
  const loadTime = performance.now() - startTime;
  pluginDetails.previousOnTraceLoadTimeMillis = loadTime;

  raf.scheduleFullRedraw();

  return result;
}

async function doPluginTraceUnload(
  pluginDetails: PluginDetails,
): Promise<void> {
  const {traceContext, plugin} = pluginDetails;

  if (traceContext) {
    plugin.onTraceUnload && (await plugin.onTraceUnload(traceContext));
    traceContext.dispose();
    pluginDetails.traceContext = undefined;
  }
}

// TODO(hjd): Sort out the story for global singletons like these:
export const pluginRegistry = new PluginRegistry();
export const pluginManager = new PluginManager(pluginRegistry);
