// Copyright (C) 2023 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 {copyToClipboard} from '../base/clipboard';
import {Trash} from '../base/disposable';
import {findRef} from '../base/dom_utils';
import {FuzzyFinder} from '../base/fuzzy';
import {assertExists, assertUnreachable} from '../base/logging';
import {undoCommonChatAppReplacements} from '../base/string_utils';
import {Actions} from '../common/actions';
import {getLegacySelection} from '../common/state';
import {
  DurationPrecision,
  setDurationPrecision,
  setTimestampFormat,
  TimestampFormat,
} from '../core/timestamp_format';
import {raf} from '../core/raf_scheduler';
import {Command, Engine, addDebugSliceTrack} from '../public';
import {HotkeyConfig, HotkeyContext} from '../widgets/hotkey_context';
import {HotkeyGlyphs} from '../widgets/hotkey_glyphs';
import {maybeRenderFullscreenModalDialog} from '../widgets/modal';

import {onClickCopy} from './clipboard';
import {CookieConsent} from './cookie_consent';
import {getTimeSpanOfSelectionOrVisibleWindow, globals} from './globals';
import {toggleHelp} from './help_modal';
import {Notes} from './notes';
import {Omnibox, OmniboxOption} from './omnibox';
import {addQueryResultsTab} from './query_result_tab';
import {executeSearch} from './search_handler';
import {Sidebar} from './sidebar';
import {Topbar} from './topbar';
import {shareTrace} from './trace_attrs';
import {AggregationsTabs} from './aggregation_tab';
import {addSqlTableTab} from './sql_table/tab';
import {SqlTables} from './sql_table/well_known_tables';
import {
  findCurrentSelection,
  focusOtherFlow,
  lockSliceSpan,
  moveByFocusedFlow,
} from './keyboard_event_handler';
import {publishPermalinkHash} from './publish';
import {OmniboxMode, PromptOption} from './omnibox_manager';
import {Utid} from './sql_types';
import {getThreadInfo} from './thread_and_process_info';
import {THREAD_STATE_TRACK_KIND} from '../core_plugins/thread_state';

function renderPermalink(): m.Children {
  const hash = globals.permalinkHash;
  if (!hash) return null;
  const url = `${self.location.origin}/#!/?s=${hash}`;
  const linkProps = {title: 'Click to copy the URL', onclick: onClickCopy(url)};

  return m('.alert-permalink', [
    m('div', 'Permalink: ', m(`a[href=${url}]`, linkProps, url)),
    m(
      'button',
      {
        onclick: () => publishPermalinkHash(undefined),
      },
      m('i.material-icons.disallow-selection', 'close'),
    ),
  ]);
}

class Alerts implements m.ClassComponent {
  view() {
    return m('.alerts', renderPermalink());
  }
}

const criticalPathSliceColumns = {
  ts: 'ts',
  dur: 'dur',
  name: 'name',
};
const criticalPathsliceColumnNames = [
  'id',
  'utid',
  'ts',
  'dur',
  'name',
  'table_name',
];

const criticalPathsliceLiteColumns = {
  ts: 'ts',
  dur: 'dur',
  name: 'thread_name',
};
const criticalPathsliceLiteColumnNames = [
  'id',
  'utid',
  'ts',
  'dur',
  'thread_name',
  'process_name',
  'table_name',
];

export class App implements m.ClassComponent {
  private trash = new Trash();
  static readonly OMNIBOX_INPUT_REF = 'omnibox';
  private omniboxInputEl?: HTMLInputElement;
  private recentCommands: string[] = [];

  constructor() {
    this.trash.add(new Notes());
    this.trash.add(new AggregationsTabs());
  }

  private getEngine(): Engine | undefined {
    const engineId = globals.getCurrentEngine()?.id;
    if (engineId === undefined) {
      return undefined;
    }
    const engine = globals.engines.get(engineId)?.getProxy('QueryPage');
    return engine;
  }

  private getFirstUtidOfSelectionOrVisibleWindow(): number {
    const selection = getLegacySelection(globals.state);
    if (selection && selection.kind === 'AREA') {
      const selectedArea = globals.state.areas[selection.areaId];
      const firstThreadStateTrack = selectedArea.tracks.find((trackId) => {
        return globals.state.tracks[trackId];
      });

      if (firstThreadStateTrack) {
        const trackInfo = globals.state.tracks[firstThreadStateTrack];
        const trackDesc = globals.trackManager.resolveTrackInfo(trackInfo.uri);
        if (
          trackDesc?.kind === THREAD_STATE_TRACK_KIND &&
          trackDesc?.utid !== undefined
        ) {
          return trackDesc?.utid;
        }
      }
    }

    return 0;
  }

  private cmds: Command[] = [
    {
      id: 'perfetto.SetTimestampFormat',
      name: 'Set timestamp and duration format',
      callback: async () => {
        const options: PromptOption[] = [
          {key: TimestampFormat.Timecode, displayName: 'Timecode'},
          {key: TimestampFormat.UTC, displayName: 'Realtime (UTC)'},
          {
            key: TimestampFormat.TraceTz,
            displayName: 'Realtime (Trace TZ)',
          },
          {key: TimestampFormat.Seconds, displayName: 'Seconds'},
          {key: TimestampFormat.Raw, displayName: 'Raw'},
          {
            key: TimestampFormat.RawLocale,
            displayName: 'Raw (with locale-specific formatting)',
          },
        ];
        const promptText = 'Select format...';

        try {
          const result = await globals.omnibox.prompt(promptText, options);
          setTimestampFormat(result as TimestampFormat);
          raf.scheduleFullRedraw();
        } catch {
          // Prompt was probably cancelled - do nothing.
        }
      },
    },
    {
      id: 'perfetto.SetDurationPrecision',
      name: 'Set duration precision',
      callback: async () => {
        const options: PromptOption[] = [
          {key: DurationPrecision.Full, displayName: 'Full'},
          {
            key: DurationPrecision.HumanReadable,
            displayName: 'Human readable',
          },
        ];
        const promptText = 'Select duration precision mode...';

        try {
          const result = await globals.omnibox.prompt(promptText, options);
          setDurationPrecision(result as DurationPrecision);
          raf.scheduleFullRedraw();
        } catch {
          // Prompt was probably cancelled - do nothing.
        }
      },
    },
    {
      id: 'perfetto.CriticalPathLite',
      name: `Critical path lite`,
      callback: async () => {
        const trackUtid = this.getFirstUtidOfSelectionOrVisibleWindow();
        const window = getTimeSpanOfSelectionOrVisibleWindow();
        const engine = this.getEngine();

        if (engine !== undefined && trackUtid != 0) {
          await engine.query(
            `INCLUDE PERFETTO MODULE sched.thread_executing_span;`,
          );
          await addDebugSliceTrack(
            engine,
            {
              sqlSource: `
                   SELECT
                      cr.id,
                      cr.utid,
                      cr.ts,
                      cr.dur,
                      thread.name AS thread_name,
                      process.name AS process_name,
                      'thread_state' AS table_name
                    FROM
                      _thread_executing_span_critical_path(
                          ${trackUtid},
                          ${window.start},
                          ${window.end} - ${window.start}) cr
                    JOIN thread USING(utid)
                    JOIN process USING(upid)
                  `,
              columns: criticalPathsliceLiteColumnNames,
            },
            (await getThreadInfo(engine, trackUtid as Utid)).name ??
              '<thread name>',
            criticalPathsliceLiteColumns,
            criticalPathsliceLiteColumnNames,
          );
        }
      },
    },
    {
      id: 'perfetto.CriticalPath',
      name: `Critical path`,
      callback: async () => {
        const trackUtid = this.getFirstUtidOfSelectionOrVisibleWindow();
        const window = getTimeSpanOfSelectionOrVisibleWindow();
        const engine = this.getEngine();

        if (engine !== undefined && trackUtid != 0) {
          await engine.query(
            `INCLUDE PERFETTO MODULE sched.thread_executing_span_with_slice;`,
          );
          await addDebugSliceTrack(
            engine,
            {
              sqlSource: `
                        SELECT cr.id, cr.utid, cr.ts, cr.dur, cr.name, cr.table_name
                        FROM
                        _critical_path_stack(
                          ${trackUtid},
                          ${window.start},
                          ${window.end} - ${window.start}, 1, 1, 1, 1) cr WHERE name IS NOT NULL
                  `,
              columns: criticalPathsliceColumnNames,
            },
            (await getThreadInfo(engine, trackUtid as Utid)).name ??
              '<thread name>',
            criticalPathSliceColumns,
            criticalPathsliceColumnNames,
          );
        }
      },
    },
    {
      id: 'perfetto.CriticalPathPprof',
      name: `Critical path pprof`,
      callback: () => {
        const trackUtid = this.getFirstUtidOfSelectionOrVisibleWindow();
        const window = getTimeSpanOfSelectionOrVisibleWindow();
        const engine = this.getEngine();

        if (engine !== undefined && trackUtid != 0) {
          addQueryResultsTab({
            query: `INCLUDE PERFETTO MODULE sched.thread_executing_span_with_slice;
                   SELECT *
                      FROM
                        _thread_executing_span_critical_path_graph(
                        "criical_path",
                         ${trackUtid},
                         ${window.start},
                         ${window.end} - ${window.start}) cr`,
            title: 'Critical path',
          });
        }
      },
    },
    {
      id: 'perfetto.ShowSliceTable',
      name: 'Open new slice table tab',
      callback: () => {
        addSqlTableTab({
          table: SqlTables.slice,
          displayName: 'slice',
        });
      },
    },
    {
      id: 'perfetto.TogglePerformanceMetrics',
      name: 'Toggle performance metrics',
      callback: () => {
        globals.dispatch(Actions.togglePerfDebug({}));
      },
    },
    {
      id: 'perfetto.ShareTrace',
      name: 'Share trace',
      callback: shareTrace,
    },
    {
      id: 'perfetto.SearchNext',
      name: 'Go to next search result',
      callback: () => {
        executeSearch();
      },
      defaultHotkey: 'Enter',
    },
    {
      id: 'perfetto.SearchPrev',
      name: 'Go to previous search result',
      callback: () => {
        executeSearch(true);
      },
      defaultHotkey: 'Shift+Enter',
    },
    {
      id: 'perfetto.OpenCommandPalette',
      name: 'Open command palette',
      callback: () => globals.omnibox.setMode(OmniboxMode.Command),
      defaultHotkey: '!Mod+Shift+P',
    },
    {
      id: 'perfetto.RunQuery',
      name: 'Run query',
      callback: () => globals.omnibox.setMode(OmniboxMode.Query),
      defaultHotkey: '!Mod+O',
    },
    {
      id: 'perfetto.Search',
      name: 'Search',
      callback: () => globals.omnibox.setMode(OmniboxMode.Search),
      defaultHotkey: '/',
    },
    {
      id: 'perfetto.ShowHelp',
      name: 'Show help',
      callback: () => toggleHelp(),
      defaultHotkey: '?',
    },
    {
      id: 'perfetto.CopyTimeWindow',
      name: `Copy selected time window to clipboard`,
      callback: () => {
        const window = getTimeSpanOfSelectionOrVisibleWindow();
        const query = `ts >= ${window.start} and ts < ${window.end}`;
        copyToClipboard(query);
      },
    },
    {
      id: 'perfetto.FocusSelection',
      name: 'Focus current selection',
      callback: () => findCurrentSelection(),
      defaultHotkey: 'F',
    },
    {
      id: 'perfetto.Deselect',
      name: 'Deselect',
      callback: () => {
        globals.timeline.deselectArea();
        globals.clearSelection();
        globals.dispatch(Actions.removeNote({id: '0'}));
      },
      defaultHotkey: 'Escape',
    },
    {
      id: 'perfetto.MarkArea',
      name: 'Mark area',
      callback: () => {
        const selection = getLegacySelection(globals.state);
        if (selection && selection.kind === 'AREA') {
          globals.dispatch(Actions.toggleMarkCurrentArea({persistent: false}));
        } else if (selection) {
          lockSliceSpan(false);
        }
      },
      defaultHotkey: 'M',
    },
    {
      id: 'perfetto.MarkAreaPersistent',
      name: 'Mark area (persistent)',
      callback: () => {
        const selection = getLegacySelection(globals.state);
        if (selection && selection.kind === 'AREA') {
          globals.dispatch(Actions.toggleMarkCurrentArea({persistent: true}));
        } else if (selection) {
          lockSliceSpan(true);
        }
      },
      defaultHotkey: 'Shift+M',
    },
    {
      id: 'perfetto.NextFlow',
      name: 'Next flow',
      callback: () => focusOtherFlow('Forward'),
      defaultHotkey: 'Mod+]',
    },
    {
      id: 'perfetto.PrevFlow',
      name: 'Prev flow',
      callback: () => focusOtherFlow('Backward'),
      defaultHotkey: 'Mod+[',
    },
    {
      id: 'perfetto.MoveNextFlow',
      name: 'Move next flow',
      callback: () => moveByFocusedFlow('Forward'),
      defaultHotkey: ']',
    },
    {
      id: 'perfetto.MovePrevFlow',
      name: 'Move prev flow',
      callback: () => moveByFocusedFlow('Backward'),
      defaultHotkey: '[',
    },
    {
      id: 'perfetto.SelectAll',
      name: 'Select all',
      callback: () => {
        let tracksToSelect: string[] = [];

        const selection = getLegacySelection(globals.state);
        if (selection !== null && selection.kind === 'AREA') {
          const area = globals.state.areas[selection.areaId];
          const coversEntireTimeRange =
            globals.traceContext.start === area.start &&
            globals.traceContext.end === area.end;
          if (!coversEntireTimeRange) {
            // If the current selection is an area which does not cover the
            // entire time range, preserve the list of selected tracks and
            // expand the time range.
            tracksToSelect = area.tracks;
          } else {
            // If the entire time range is already covered, update the selection
            // to cover all tracks.
            tracksToSelect = Object.keys(globals.state.tracks);
          }
        } else {
          // If the current selection is not an area, select all.
          tracksToSelect = Object.keys(globals.state.tracks);
        }
        const {start, end} = globals.traceContext;
        globals.dispatch(
          Actions.selectArea({
            area: {
              start,
              end,
              tracks: tracksToSelect,
            },
          }),
        );
      },
      defaultHotkey: 'Mod+A',
    },
  ];

  commands() {
    return this.cmds;
  }

  private renderOmnibox(): m.Children {
    const msgTTL = globals.state.status.timestamp + 1 - Date.now() / 1e3;
    const engineIsBusy =
      globals.state.engine !== undefined && !globals.state.engine.ready;

    if (msgTTL > 0 || engineIsBusy) {
      setTimeout(() => raf.scheduleFullRedraw(), msgTTL * 1000);
      return m(
        `.omnibox.message-mode`,
        m(`input[readonly][disabled][ref=omnibox]`, {
          value: '',
          placeholder: globals.state.status.msg,
        }),
      );
    }

    const omniboxMode = globals.omnibox.omniboxMode;

    if (omniboxMode === OmniboxMode.Command) {
      return this.renderCommandOmnibox();
    } else if (omniboxMode === OmniboxMode.Prompt) {
      return this.renderPromptOmnibox();
    } else if (omniboxMode === OmniboxMode.Query) {
      return this.renderQueryOmnibox();
    } else if (omniboxMode === OmniboxMode.Search) {
      return this.renderSearchOmnibox();
    } else {
      assertUnreachable(omniboxMode);
    }
  }

  renderPromptOmnibox(): m.Children {
    const prompt = assertExists(globals.omnibox.pendingPrompt);

    let options: OmniboxOption[] | undefined = undefined;

    if (prompt.options) {
      const fuzzy = new FuzzyFinder(
        prompt.options,
        ({displayName}) => displayName,
      );
      const result = fuzzy.find(globals.omnibox.text);
      options = result.map((result) => {
        return {
          key: result.item.key,
          displayName: result.segments,
        };
      });
    }

    return m(Omnibox, {
      value: globals.omnibox.text,
      placeholder: prompt.text,
      inputRef: App.OMNIBOX_INPUT_REF,
      extraClasses: 'prompt-mode',
      closeOnOutsideClick: true,
      options,
      selectedOptionIndex: globals.omnibox.omniboxSelectionIndex,
      onSelectedOptionChanged: (index) => {
        globals.omnibox.setOmniboxSelectionIndex(index);
        raf.scheduleFullRedraw();
      },
      onInput: (value) => {
        globals.omnibox.setText(value);
        globals.omnibox.setOmniboxSelectionIndex(0);
        raf.scheduleFullRedraw();
      },
      onSubmit: (value, _alt) => {
        globals.omnibox.resolvePrompt(value);
      },
      onClose: () => {
        globals.omnibox.rejectPrompt();
      },
    });
  }

  renderCommandOmnibox(): m.Children {
    const cmdMgr = globals.commandManager;

    // Fuzzy-filter commands by the filter string.
    const filteredCmds = cmdMgr.fuzzyFilterCommands(globals.omnibox.text);

    // Create an array of commands with attached heuristics from the recent
    // command register.
    const commandsWithHeuristics = filteredCmds.map((cmd) => {
      return {
        recentsIndex: this.recentCommands.findIndex((id) => id === cmd.id),
        cmd,
      };
    });

    // Sort by recentsIndex then by alphabetical order
    const sorted = commandsWithHeuristics.sort((a, b) => {
      if (b.recentsIndex === a.recentsIndex) {
        return a.cmd.name.localeCompare(b.cmd.name);
      } else {
        return b.recentsIndex - a.recentsIndex;
      }
    });

    const options = sorted.map(({recentsIndex, cmd}): OmniboxOption => {
      const {segments, id, defaultHotkey} = cmd;
      return {
        key: id,
        displayName: segments,
        tag: recentsIndex !== -1 ? 'recently used' : undefined,
        rightContent: defaultHotkey && m(HotkeyGlyphs, {hotkey: defaultHotkey}),
      };
    });

    return m(Omnibox, {
      value: globals.omnibox.text,
      placeholder: 'Filter commands...',
      inputRef: App.OMNIBOX_INPUT_REF,
      extraClasses: 'command-mode',
      options,
      closeOnSubmit: true,
      closeOnOutsideClick: true,
      selectedOptionIndex: globals.omnibox.omniboxSelectionIndex,
      onSelectedOptionChanged: (index) => {
        globals.omnibox.setOmniboxSelectionIndex(index);
        raf.scheduleFullRedraw();
      },
      onInput: (value) => {
        globals.omnibox.setText(value);
        globals.omnibox.setOmniboxSelectionIndex(0);
        raf.scheduleFullRedraw();
      },
      onClose: () => {
        if (this.omniboxInputEl) {
          this.omniboxInputEl.blur();
        }
        globals.omnibox.reset();
      },
      onSubmit: (key: string) => {
        this.addRecentCommand(key);
        cmdMgr.runCommand(key);
      },
      onGoBack: () => {
        globals.omnibox.reset();
      },
    });
  }

  private addRecentCommand(id: string): void {
    this.recentCommands = this.recentCommands.filter((x) => x !== id);
    this.recentCommands.push(id);
    while (this.recentCommands.length > 6) {
      this.recentCommands.shift();
    }
  }

  renderQueryOmnibox(): m.Children {
    const ph = 'e.g. select * from sched left join thread using(utid) limit 10';
    return m(Omnibox, {
      value: globals.omnibox.text,
      placeholder: ph,
      inputRef: App.OMNIBOX_INPUT_REF,
      extraClasses: 'query-mode',

      onInput: (value) => {
        globals.omnibox.setText(value);
        raf.scheduleFullRedraw();
      },
      onSubmit: (query, alt) => {
        const config = {
          query: undoCommonChatAppReplacements(query),
          title: alt ? 'Pinned query' : 'Omnibox query',
        };
        const tag = alt ? undefined : 'omnibox_query';
        addQueryResultsTab(config, tag);
      },
      onClose: () => {
        globals.omnibox.setText('');
        if (this.omniboxInputEl) {
          this.omniboxInputEl.blur();
        }
        globals.omnibox.reset();
        raf.scheduleFullRedraw();
      },
      onGoBack: () => {
        globals.omnibox.reset();
      },
    });
  }

  renderSearchOmnibox(): m.Children {
    const omniboxState = globals.state.omniboxState;
    const displayStepThrough =
      omniboxState.omnibox.length >= 4 || omniboxState.force;

    return m(Omnibox, {
      value: globals.state.omniboxState.omnibox,
      placeholder: "Search or type '>' for commands or ':' for SQL mode",
      inputRef: App.OMNIBOX_INPUT_REF,
      onInput: (value, prev) => {
        if (prev === '') {
          if (value === '>') {
            globals.omnibox.setMode(OmniboxMode.Command);
            return;
          } else if (value === ':') {
            globals.omnibox.setMode(OmniboxMode.Query);
            return;
          }
        }
        globals.dispatch(Actions.setOmnibox({omnibox: value, mode: 'SEARCH'}));
      },
      onClose: () => {
        if (this.omniboxInputEl) {
          this.omniboxInputEl.blur();
        }
      },
      onSubmit: (value, _mod, shift) => {
        executeSearch(shift);
        globals.dispatch(
          Actions.setOmnibox({omnibox: value, mode: 'SEARCH', force: true}),
        );
        if (this.omniboxInputEl) {
          this.omniboxInputEl.blur();
        }
      },
      rightContent: displayStepThrough && this.renderStepThrough(),
    });
  }

  private renderStepThrough() {
    return m(
      '.stepthrough',
      m(
        '.current',
        `${
          globals.currentSearchResults.totalResults === 0
            ? '0 / 0'
            : `${globals.state.searchIndex + 1} / ${
                globals.currentSearchResults.totalResults
              }`
        }`,
      ),
      m(
        'button',
        {
          onclick: () => {
            executeSearch(true /* reverse direction */);
          },
        },
        m('i.material-icons.left', 'keyboard_arrow_left'),
      ),
      m(
        'button',
        {
          onclick: () => {
            executeSearch();
          },
        },
        m('i.material-icons.right', 'keyboard_arrow_right'),
      ),
    );
  }

  view({children}: m.Vnode): m.Children {
    const hotkeys: HotkeyConfig[] = [];
    const commands = globals.commandManager.commands;
    for (const {id, defaultHotkey} of commands) {
      if (defaultHotkey) {
        hotkeys.push({
          callback: () => {
            globals.commandManager.runCommand(id);
          },
          hotkey: defaultHotkey,
        });
      }
    }

    return m(
      HotkeyContext,
      {hotkeys},
      m(
        'main',
        m(Sidebar),
        m(Topbar, {
          omnibox: this.renderOmnibox(),
        }),
        m(Alerts),
        children,
        m(CookieConsent),
        maybeRenderFullscreenModalDialog(),
        globals.state.perfDebug && m('.perf-stats'),
      ),
    );
  }

  oncreate({dom}: m.VnodeDOM) {
    this.updateOmniboxInputRef(dom);
    this.maybeFocusOmnibar();

    // Register each command with the command manager
    this.cmds.forEach((cmd) => {
      const dispose = globals.commandManager.registerCommand(cmd);
      this.trash.add(dispose);
    });
  }

  onupdate({dom}: m.VnodeDOM) {
    this.updateOmniboxInputRef(dom);
    this.maybeFocusOmnibar();
  }

  onremove(_: m.VnodeDOM) {
    this.trash.dispose();
    this.omniboxInputEl = undefined;
  }

  private updateOmniboxInputRef(dom: Element): void {
    const el = findRef(dom, App.OMNIBOX_INPUT_REF);
    if (el && el instanceof HTMLInputElement) {
      this.omniboxInputEl = el;
    }
  }

  private maybeFocusOmnibar() {
    if (globals.omnibox.focusOmniboxNextRender) {
      const omniboxEl = this.omniboxInputEl;
      if (omniboxEl) {
        omniboxEl.focus();
        if (globals.omnibox.pendingCursorPlacement === undefined) {
          omniboxEl.select();
        } else {
          omniboxEl.setSelectionRange(
            globals.omnibox.pendingCursorPlacement,
            globals.omnibox.pendingCursorPlacement,
          );
        }
      }
      globals.omnibox.clearOmniboxFocusFlag();
    }
  }
}
