// 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 m from 'mithril';
import {v4 as uuidv4} from 'uuid';

import {Actions} from '../common/actions';
import {EngineProxy} from '../common/engine';
import {Registry} from '../common/registry';
import {globals} from './globals';

import {Panel, PanelSize, PanelVNode} from './panel';

export interface NewBottomTabArgs {
  engine: EngineProxy;
  tag?: string;
  uuid: string;
  config: {};
}

// Interface for allowing registration and creation of bottom tabs.
// See comments on |TrackCreator| for more details.
export interface BottomTabCreator {
  readonly kind: string;

  create(args: NewBottomTabArgs): BottomTab;
}

export const bottomTabRegistry = Registry.kindRegistry<BottomTabCreator>();

// Period to wait for the newly-added tabs which are loading before showing
// them to the user. This period is short enough to not be user-visible,
// while being long enough for most of the simple queries to complete, reducing
// flickering in the UI.
const NEW_LOADING_TAB_DELAY_MS = 50;

// An interface representing a bottom tab displayed on the panel in the bottom
// of the ui (e.g. "Current Selection").
//
// The implementations of this class are provided by different plugins, which
// register the implementations with bottomTabRegistry, keyed by a unique name
// for each type of BottomTab.
//
// Lifetime: the instances of this class are owned by BottomTabPanel and exist
// for as long as a tab header is shown to the user in the bottom tab list (with
// minor exceptions, like a small grace period between when the tab is related).
//
// BottomTab implementations should pass the unique identifier(s) for the
// content displayed via the |Config| and fetch additional details via Engine
// instead of relying on getting the data from the global storage. For example,
// for tabs corresponding to details of the selected objects on a track, a new
// BottomTab should be created for each new selection.
export abstract class BottomTabBase<Config = {}> {
  // Config for this details panel. Should be serializable.
  protected readonly config: Config;
  // Engine for running queries and fetching additional data.
  protected readonly engine: EngineProxy;
  // Optional tag, which is used to ensure that only one tab
  // with the same tag can exist - adding a new tab with the same tag
  // (e.g. 'current_selection') would close the previous one. This
  // also can be used to close existing tab.
  readonly tag?: string;
  // Unique id for this details panel. Can be used to close previously opened
  // panel.
  readonly uuid: string;

  constructor(args: NewBottomTabArgs) {
    this.config = args.config as Config;
    this.engine = args.engine;
    this.tag = args.tag;
    this.uuid = args.uuid;
  }

  // Entry point for customisation of the displayed title for this panel.
  abstract getTitle(): string;

  // Generate a mithril node for this component.
  abstract createPanelVnode(): PanelVNode;

  // API for the tab to notify the TabList that it's still preparing the data.
  // If true, adding a new tab will be delayed for a short while (~50ms) to
  // reduce the flickering.
  //
  // Note: it's a "poll" rather than "push" API: there is no explicit API
  // for the tabs to notify the tab list, as the tabs are expected to schedule
  // global redraw anyway and the tab list will poll the tabs as necessary
  // during the redraw.
  isLoading(): boolean {
    return false;
  }
}


// BottomTabBase provides a more generic API allowing users to provide their
// custom mithril component, which would allow them to listen to mithril
// lifecycle events. Most cases, however, don't need them and BottomTab
// provides a simplified API for the common case.
export abstract class BottomTab<Config = {}> extends BottomTabBase<Config> {
  constructor(args: NewBottomTabArgs) {
    super(args);
  }

  // These methods are direct counterparts to renderCanvas and view with
  // slightly changes names to prevent cases when `BottomTab` will
  // be accidentally used a mithril component.
  abstract renderTabCanvas(ctx: CanvasRenderingContext2D, size: PanelSize):
      void;
  abstract viewTab(): void|m.Children;

  createPanelVnode(): m.Vnode<any, any> {
    return m(
        BottomTabAdapter,
        {key: this.uuid, panel: this} as BottomTabAdapterAttrs);
  }
}

interface BottomTabAdapterAttrs {
  panel: BottomTab;
}

class BottomTabAdapter extends Panel<BottomTabAdapterAttrs> {
  renderCanvas(
      ctx: CanvasRenderingContext2D, size: PanelSize,
      vnode: PanelVNode<BottomTabAdapterAttrs>): void {
    vnode.attrs.panel.renderTabCanvas(ctx, size);
  }

  view(vnode: m.CVnode<BottomTabAdapterAttrs>): void|m.Children {
    return vnode.attrs.panel.viewTab();
  }
}

export type AddTabArgs = {
  kind: string,
  config: {},
  tag?: string,
  // Whether to make the new tab current. True by default.
  select?: boolean;
};

export type AddTabResult =
    {
      uuid: string;
    }

// Shorthand for globals.bottomTabList.addTab(...) & redraw.
// Ignored when bottomTabList does not exist (e.g. no trace is open in the UI).
export function
addTab(args: AddTabArgs) {
  const tabList = globals.bottomTabList;
  if (!tabList) {
    return;
  }
  tabList.addTab(args);
  globals.rafScheduler.scheduleFullRedraw();
}


// Shorthand for globals.bottomTabList.closeTabById(...) & redraw.
// Ignored when bottomTabList does not exist (e.g. no trace is open in the UI).
export function
closeTab(uuid: string) {
  const tabList = globals.bottomTabList;
  if (!tabList) {
    return;
  }
  tabList.closeTabById(uuid);
  globals.rafScheduler.scheduleFullRedraw();
}

interface PendingTab {
  tab: BottomTabBase, args: AddTabArgs, startTime: number,
}

function tabSelectionKey(tab: BottomTabBase) {
  return tab.tag ?? tab.uuid;
}

export class BottomTabList {
  private tabs: BottomTabBase[] = [];
  private pendingTabs: PendingTab[] = [];
  private engine: EngineProxy;
  private scheduledFlushSetTimeoutId?: number;

  constructor(engine: EngineProxy) {
    this.engine = engine;
  }

  getTabs(): BottomTabBase[] {
    this.flushPendingTabs();
    return this.tabs;
  }

  // Add and create a new panel with given kind and config, replacing an
  // existing panel with the same tag if needed. Returns the uuid of a newly
  // created panel (which can be used in the future to close it).
  addTab(args: AddTabArgs): AddTabResult {
    const uuid = uuidv4();
    const newPanel = bottomTabRegistry.get(args.kind).create({
      engine: this.engine,
      uuid,
      config: args.config,
      tag: args.tag,
    });

    this.pendingTabs.push({
      tab: newPanel,
      args,
      startTime: window.performance.now(),
    });
    this.flushPendingTabs();

    return {
      uuid,
    };
  }

  closeTabByTag(tag: string) {
    const index = this.tabs.findIndex((tab) => tab.tag === tag);
    if (index !== -1) {
      this.removeTabAtIndex(index);
    }
    // User closing a tab by tag should affect pending tabs as well, as these
    // tabs were requested to be added to the tab list before this call.
    this.pendingTabs = this.pendingTabs.filter(({tab}) => tab.tag !== tag);
  }

  closeTabById(uuid: string) {
    const index = this.tabs.findIndex((tab) => tab.uuid === uuid);
    if (index !== -1) {
      this.removeTabAtIndex(index);
    }
    // User closing a tab by id should affect pending tabs as well, as these
    // tabs were requested to be added to the tab list before this call.
    this.pendingTabs = this.pendingTabs.filter(({tab}) => tab.uuid !== uuid);
  }

  private removeTabAtIndex(index: number) {
    const tab = this.tabs[index];
    this.tabs.splice(index, 1);
    // If the current tab was closed, select the tab to the right of it.
    // If the closed tab was current and last in the tab list, select the tab
    // that became last.
    if (tab.uuid === globals.state.currentTab && this.tabs.length > 0) {
      const newActiveIndex = index === this.tabs.length ? index - 1 : index;
      globals.dispatch(Actions.setCurrentTab(
          {tab: tabSelectionKey(this.tabs[newActiveIndex])}));
    }
    globals.rafScheduler.scheduleFullRedraw();
  }

  // Check the list of the pending tabs and add the ones that are ready
  // (either tab.isLoading returns false or NEW_LOADING_TAB_DELAY_MS ms elapsed
  // since this tab was added).
  // Note: the pending tabs are stored in a queue to preserve the action order,
  // which matters for cases like adding tabs with the same tag.
  private flushPendingTabs() {
    const currentTime = window.performance.now();
    while (this.pendingTabs.length > 0) {
      const {tab, args, startTime} = this.pendingTabs[0];

      // This is a dirty hack^W^W low-lift solution for the world where some
      // "current selection" panels are implemented by BottomTabs and some by
      // details_panel.ts computing vnodes dynamically. Naive implementation
      // will: a) stop showing the old panel (because
      // globals.state.currentSelection changes). b) not showing the new
      // 'current_selection' tab yet. This will result in temporary shifting
      // focus to another tab (as no tab with 'current_selection' tag will
      // exist).
      //
      // To counteract this, short-circuit this logic and when:
      // a) no tag with 'current_selection' tag exists in the list of currently
      // displayed tabs and b) we are adding a tab with 'current_selection' tag.
      // add it immediately without waiting.
      // TODO(altimin): Remove this once all places have switched to be using
      // BottomTab to display panels.
      const currentSelectionTabAlreadyExists =
          this.tabs.filter((tab) => tab.tag === 'current_selection').length > 0;
      const dirtyHackForCurrentSelectionApplies =
          tab.tag === 'current_selection' && !currentSelectionTabAlreadyExists;

      const elapsedTimeMs = currentTime - startTime;
      if (tab.isLoading() && elapsedTimeMs < NEW_LOADING_TAB_DELAY_MS &&
          !dirtyHackForCurrentSelectionApplies) {
        this.schedulePendingTabsFlush(NEW_LOADING_TAB_DELAY_MS - elapsedTimeMs);
        // The first tab is not ready yet, wait.
        return;
      }
      this.pendingTabs.shift();

      const index =
          args.tag ? this.tabs.findIndex((tab) => tab.tag === args.tag) : -1;
      if (index === -1) {
        this.tabs.push(tab);
      } else {
        this.tabs[index] = tab;
      }

      if (args.select === undefined || args.select === true) {
        globals.dispatch(Actions.setCurrentTab({tab: tabSelectionKey(tab)}));
      }
    }
  }

  private schedulePendingTabsFlush(waitTimeMs: number) {
    if (this.scheduledFlushSetTimeoutId) {
      // The flush is already pending, no action is required.
      return;
    }
    setTimeout(() => {
      this.scheduledFlushSetTimeoutId = undefined;
      this.flushPendingTabs();
    }, waitTimeMs);
  }
}
