// Copyright (C) 2018 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 {BigintMath} from '../base/bigint_math';
import {assertExists, assertTrue} from '../base/logging';
import {
  Duration,
  duration,
  Span,
  time,
  Time,
  TimeSpan,
} from '../base/time';
import {
  Actions,
  DeferredAction,
} from '../common/actions';
import {cacheTrace} from '../common/cache_manager';
import {
  HighPrecisionTime,
  HighPrecisionTimeSpan,
} from '../common/high_precision_time';
import {
  getEnabledMetatracingCategories,
  isMetatracingEnabled,
} from '../common/metatracing';
import {pluginManager} from '../common/plugins';
import {onSelectionChanged} from '../common/selection_observer';
import {
  defaultTraceTime,
  EngineMode,
  PendingDeeplinkState,
  ProfileType,
} from '../common/state';
import {featureFlags, Flag, PERF_SAMPLE_FLAG} from '../core/feature_flags';
import {BottomTabList} from '../frontend/bottom_tab';
import {
  FtraceStat,
  globals,
  QuantizedLoad,
  ThreadDesc,
} from '../frontend/globals';
import {
  clearOverviewData,
  publishFtraceCounters,
  publishMetricError,
  publishOverviewData,
  publishRealtimeOffset,
  publishThreads,
} from '../frontend/publish';
import {addQueryResultsTab} from '../frontend/query_result_tab';
import {Router} from '../frontend/router';
import {Engine} from '../trace_processor/engine';
import {HttpRpcEngine} from '../trace_processor/http_rpc_engine';
import {
  LONG,
  LONG_NULL,
  NUM,
  NUM_NULL,
  QueryError,
  STR,
  STR_NULL,
} from '../trace_processor/query_result';
import {
  resetEngineWorker,
  WasmEngineProxy,
} from '../trace_processor/wasm_engine_proxy';
import {showModal} from '../widgets/modal';

import {
  CounterAggregationController,
} from './aggregation/counter_aggregation_controller';
import {
  CpuAggregationController,
} from './aggregation/cpu_aggregation_controller';
import {
  CpuByProcessAggregationController,
} from './aggregation/cpu_by_process_aggregation_controller';
import {
  FrameAggregationController,
} from './aggregation/frame_aggregation_controller';
import {
  SliceAggregationController,
} from './aggregation/slice_aggregation_controller';
import {
  ThreadAggregationController,
} from './aggregation/thread_aggregation_controller';
import {Child, Children, Controller} from './controller';
import {
  CpuProfileController,
  CpuProfileControllerArgs,
} from './cpu_profile_controller';
import {
  FlamegraphController,
  FlamegraphControllerArgs,
  profileType,
} from './flamegraph_controller';
import {
  FlowEventsController,
  FlowEventsControllerArgs,
} from './flow_events_controller';
import {FtraceController} from './ftrace_controller';
import {LoadingManager} from './loading_manager';
import {LogsController} from './logs_controller';
import {
  PIVOT_TABLE_REDUX_FLAG,
  PivotTableController,
} from './pivot_table_controller';
import {SearchController} from './search_controller';
import {
  SelectionController,
  SelectionControllerArgs,
} from './selection_controller';
import {
  TraceErrorController,
} from './trace_error_controller';
import {
  TraceBufferStream,
  TraceFileStream,
  TraceHttpStream,
  TraceStream,
} from './trace_stream';
import {decideTracks} from './track_decider';

type States = 'init' | 'loading_trace' | 'ready';

const METRICS = [
  'android_startup',
  'android_ion',
  'android_lmk',
  'android_dma_heap',
  'android_surfaceflinger',
  'android_batt',
  'android_other_traces',
  'chrome_dropped_frames',
  // TODO(289365196): Reenable:
  // 'chrome_long_latency',
  'trace_metadata',
  'android_trusty_workqueues',
];
const FLAGGED_METRICS: Array<[Flag, string]> = METRICS.map((m) => {
  const id = `forceMetric${m}`;
  let name = m.split('_').join(' ');
  name = name[0].toUpperCase() + name.slice(1);
  name = 'Metric: ' + name;
  const flag = featureFlags.register({
    id,
    name,
    description: `Overrides running the '${m}' metric at import time.`,
    defaultValue: true,
  });
  return [flag, m];
});

const ENABLE_CHROME_RELIABLE_RANGE_ZOOM_FLAG = featureFlags.register({
  id: 'enableChromeReliableRangeZoom',
  name: 'Enable Chrome reliable range zoom',
  description: 'Automatically zoom into the reliable range for Chrome traces',
  defaultValue: false,
});

const ENABLE_CHROME_RELIABLE_RANGE_ANNOTATION_FLAG = featureFlags.register({
  id: 'enableChromeReliableRangeAnnotation',
  name: 'Enable Chrome reliable range annotation',
  description: 'Automatically adds an annotation for the reliable range start',
  defaultValue: false,
});

// The following flags control TraceProcessor Config.
const CROP_TRACK_EVENTS_FLAG = featureFlags.register({
  id: 'cropTrackEvents',
  name: 'Crop track events',
  description: 'Ignores track events outside of the range of interest',
  defaultValue: false,
});
const INGEST_FTRACE_IN_RAW_TABLE_FLAG = featureFlags.register({
  id: 'ingestFtraceInRawTable',
  name: 'Ingest ftrace in raw table',
  description: 'Enables ingestion of typed ftrace events into the raw table',
  defaultValue: true,
});
const ANALYZE_TRACE_PROTO_CONTENT_FLAG = featureFlags.register({
  id: 'analyzeTraceProtoContent',
  name: 'Analyze trace proto content',
  description: 'Enables trace proto content analysis',
  defaultValue: false,
});

// A local storage key where the indication that JSON warning has been shown is
// stored.
const SHOWN_JSON_WARNING_KEY = 'shownJsonWarning';

function showJsonWarning() {
  showModal({
    title: 'Warning',
    content:
      m('div',
        m('span',
          'Perfetto UI features are limited for JSON traces. ',
          'We recommend recording ',
          m('a',
            {href: 'https://perfetto.dev/docs/quickstart/chrome-tracing'},
            'proto-format traces'),
          ' from Chrome.'),
        m('br')),
    buttons: [],
  });
}

// TODO(stevegolton): Move this into some global "SQL extensions" file and
// ensure it's only run once.
async function defineMaxLayoutDepthSqlFunction(engine: Engine): Promise<void> {
  await engine.query(`
    select create_function(
      'max_layout_depth(track_count INT, track_ids STRING)',
      'INT',
      '
        select iif(
          $track_count = 1,
          (
            select max(depth)
            from slice
            where track_id = cast($track_ids AS int)
          ),
          (
            select max(layout_depth)
            from experimental_slice_layout($track_ids)
          )
        );
      '
    );
  `);
}

// TraceController handles handshakes with the frontend for everything that
// concerns a single trace. It owns the WASM trace processor engine, handles
// tracks data and SQL queries. There is one TraceController instance for each
// trace opened in the UI (for now only one trace is supported).
export class TraceController extends Controller<States> {
  private readonly engineId: string;
  private engine?: Engine;

  constructor(engineId: string) {
    super('init');
    this.engineId = engineId;
  }

  run() {
    const engineCfg = assertExists(globals.state.engine);
    switch (this.state) {
    case 'init':
      this.loadTrace()
        .then((mode) => {
          globals.dispatch(Actions.setEngineReady({
            engineId: this.engineId,
            ready: true,
            mode,
          }));
        })
        .catch((err) => {
          this.updateStatus(`${err}`);
          throw err;
        });
      this.updateStatus('Opening trace');
      this.setState('loading_trace');
      break;

    case 'loading_trace':
      // Stay in this state until loadTrace() returns and marks the engine as
      // ready.
      if (this.engine === undefined || !engineCfg.ready) return;
      this.setState('ready');
      break;

    case 'ready':
      // At this point we are ready to serve queries and handle tracks.
      const engine = assertExists(this.engine);
      const childControllers: Children = [];

      const selectionArgs: SelectionControllerArgs = {engine};
      childControllers.push(
        Child('selection', SelectionController, selectionArgs));

      const flowEventsArgs: FlowEventsControllerArgs = {engine};
      childControllers.push(
        Child('flowEvents', FlowEventsController, flowEventsArgs));

      const cpuProfileArgs: CpuProfileControllerArgs = {engine};
      childControllers.push(
        Child('cpuProfile', CpuProfileController, cpuProfileArgs));

      const flamegraphArgs: FlamegraphControllerArgs = {engine};
      childControllers.push(
        Child('flamegraph', FlamegraphController, flamegraphArgs));
      childControllers.push(Child(
        'cpu_aggregation',
        CpuAggregationController,
        {engine, kind: 'cpu_aggregation'}));
      childControllers.push(Child(
        'thread_aggregation',
        ThreadAggregationController,
        {engine, kind: 'thread_state_aggregation'}));
      childControllers.push(Child(
        'cpu_process_aggregation',
        CpuByProcessAggregationController,
        {engine, kind: 'cpu_by_process_aggregation'}));
      if (!PIVOT_TABLE_REDUX_FLAG.get()) {
        // Pivot table is supposed to handle the use cases the slice
        // aggregation panel is used right now. When a flag to use pivot
        // tables is enabled, do not add slice aggregation controller.
        childControllers.push(Child(
          'slice_aggregation',
          SliceAggregationController,
          {engine, kind: 'slice_aggregation'}));
      }
      childControllers.push(Child(
        'counter_aggregation',
        CounterAggregationController,
        {engine, kind: 'counter_aggregation'}));
      childControllers.push(Child(
        'frame_aggregation',
        FrameAggregationController,
        {engine, kind: 'frame_aggregation'}));
      childControllers.push(Child('search', SearchController, {
        engine,
        app: globals,
      }));
      childControllers.push(
        Child('pivot_table', PivotTableController, {engine}));

      childControllers.push(Child('logs', LogsController, {
        engine,
        app: globals,
      }));

      childControllers.push(
        Child('ftrace', FtraceController, {engine, app: globals}));

      childControllers.push(
        Child('traceError', TraceErrorController, {engine}));

      return childControllers;

    default:
      throw new Error(`unknown state ${this.state}`);
    }
    return;
  }

  onDestroy() {
    pluginManager.onTraceClose();
    globals.engines.delete(this.engineId);
  }

  private async loadTrace(): Promise<EngineMode> {
    this.updateStatus('Creating trace processor');
    // Check if there is any instance of the trace_processor_shell running in
    // HTTP RPC mode (i.e. trace_processor_shell -D).
    let engineMode: EngineMode;
    let useRpc = false;
    if (globals.state.newEngineMode === 'USE_HTTP_RPC_IF_AVAILABLE') {
      useRpc = (await HttpRpcEngine.checkConnection()).connected;
    }
    let engine;
    if (useRpc) {
      console.log('Opening trace using native accelerator over HTTP+RPC');
      engineMode = 'HTTP_RPC';
      engine = new HttpRpcEngine(this.engineId, LoadingManager.getInstance);
      engine.errorHandler = (err) => {
        globals.dispatch(
          Actions.setEngineFailed({mode: 'HTTP_RPC', failure: `${err}`}));
        throw err;
      };
    } else {
      console.log('Opening trace using built-in WASM engine');
      engineMode = 'WASM';
      const enginePort = resetEngineWorker();
      engine = new WasmEngineProxy(
        this.engineId, enginePort, LoadingManager.getInstance);
      engine.resetTraceProcessor({
        cropTrackEvents: CROP_TRACK_EVENTS_FLAG.get(),
        ingestFtraceInRawTable: INGEST_FTRACE_IN_RAW_TABLE_FLAG.get(),
        analyzeTraceProtoContent: ANALYZE_TRACE_PROTO_CONTENT_FLAG.get(),
      });
    }
    this.engine = engine;

    if (isMetatracingEnabled()) {
      this.engine.enableMetatrace(
        assertExists(getEnabledMetatracingCategories()));
    }
    globals.bottomTabList = new BottomTabList(engine.getProxy('BottomTabList'));

    globals.engines.set(this.engineId, engine);
    globals.dispatch(Actions.setEngineReady({
      engineId: this.engineId,
      ready: false,
      mode: engineMode,
    }));
    const engineCfg = assertExists(globals.state.engine);
    assertTrue(engineCfg.id === this.engineId);
    let traceStream: TraceStream | undefined;
    if (engineCfg.source.type === 'FILE') {
      traceStream = new TraceFileStream(engineCfg.source.file);
    } else if (engineCfg.source.type === 'ARRAY_BUFFER') {
      traceStream = new TraceBufferStream(engineCfg.source.buffer);
    } else if (engineCfg.source.type === 'URL') {
      traceStream = new TraceHttpStream(engineCfg.source.url);
    } else if (engineCfg.source.type === 'HTTP_RPC') {
      traceStream = undefined;
    } else {
      throw new Error(`Unknown source: ${JSON.stringify(engineCfg.source)}`);
    }

    // |traceStream| can be undefined in the case when we are using the external
    // HTTP+RPC endpoint and the trace processor instance has already loaded
    // a trace (because it was passed as a cmdline argument to
    // trace_processor_shell). In this case we don't want the UI to load any
    // file/stream and we just want to jump to the loading phase.
    if (traceStream !== undefined) {
      const tStart = performance.now();
      for (; ;) {
        const res = await traceStream.readChunk();
        await this.engine.parse(res.data);
        const elapsed = (performance.now() - tStart) / 1000;
        let status = 'Loading trace ';
        if (res.bytesTotal > 0) {
          const progress = Math.round(res.bytesRead / res.bytesTotal * 100);
          status += `${progress}%`;
        } else {
          status += `${Math.round(res.bytesRead / 1e6)} MB`;
        }
        status += ` - ${Math.ceil(res.bytesRead / elapsed / 1e6)} MB/s`;
        this.updateStatus(status);
        if (res.eof) break;
      }
      await this.engine.notifyEof();
    } else {
      assertTrue(this.engine instanceof HttpRpcEngine);
      await this.engine.restoreInitialTables();
    }

    // traceUuid will be '' if the trace is not cacheable (URL or RPC).
    const traceUuid = await this.cacheCurrentTrace();

    const traceTime = await this.engine.getTraceTimeBounds();
    const start = traceTime.start;
    const end = traceTime.end;
    const traceTimeState = {
      start,
      end,
    };

    const shownJsonWarning =
      window.localStorage.getItem(SHOWN_JSON_WARNING_KEY) !== null;

    // Show warning if the trace is in JSON format.
    const query = `select str_value from metadata where name = 'trace_type'`;
    const result = await assertExists(this.engine).query(query);
    const traceType = result.firstRow({str_value: STR}).str_value;
    const isJsonTrace = traceType == 'json';
    if (!shownJsonWarning) {
      // When in embedded mode, the host app will control which trace format
      // it passes to Perfetto, so we don't need to show this warning.
      if (isJsonTrace && !globals.embeddedMode) {
        showJsonWarning();
        // Save that the warning has been shown. Value is irrelevant since only
        // the presence of key is going to be checked.
        window.localStorage.setItem(SHOWN_JSON_WARNING_KEY, 'true');
      }
    }

    const emptyOmniboxState = {
      omnibox: '',
      mode: globals.state.omniboxState.mode || 'SEARCH',
    };

    const actions: DeferredAction[] = [
      Actions.setOmnibox(emptyOmniboxState),
      Actions.setTraceUuid({traceUuid}),
      Actions.setTraceTime(traceTimeState),
    ];

    const visibleTimeSpan = await computeVisibleTime(
      traceTime.start, traceTime.end, isJsonTrace, this.engine);
    // We don't know the resolution at this point. However this will be
    // replaced in 50ms so a guess is fine.
    const resolution = visibleTimeSpan.duration.divide(1000).toTime();
    actions.push(Actions.setVisibleTraceTime({
      start: visibleTimeSpan.start.toTime(),
      end: visibleTimeSpan.end.toTime(),
      lastUpdate: Date.now() / 1000,
      resolution: BigintMath.max(resolution, 1n),
    }));

    globals.dispatchMultiple(actions);
    Router.navigate(`#!/viewer?local_cache_key=${traceUuid}`);

    // Make sure the helper views are available before we start adding tracks.
    await this.initialiseHelperViews();

    await defineMaxLayoutDepthSqlFunction(engine);

    this.updateStatus('Loading plugins');
    await pluginManager.onTraceLoad(engine);

    {
      // When we reload from a permalink don't create extra tracks:
      const {pinnedTracks, tracks} = globals.state;
      if (!pinnedTracks.length && !Object.keys(tracks).length) {
        await this.listTracks();
      }
    }

    this.decideTabs();

    await this.listThreads();
    await this.loadTimelineOverview(traceTime);

    {
      // Pull out the counts ftrace events by name
      const query = `select
            name,
            count(name) as cnt
          from ftrace_event
          group by name
          order by cnt desc`;
      const result = await assertExists(this.engine).query(query);
      const counters: FtraceStat[] = [];
      const it = result.iter({name: STR, cnt: NUM});
      for (let row = 0; it.valid(); it.next(), row++) {
        counters.push({name: it.name, count: it.cnt});
      }
      publishFtraceCounters(counters);
    }

    {
      // Find the first REALTIME or REALTIME_COARSE clock snapshot.
      // Prioritize REALTIME over REALTIME_COARSE.
      const query = `select
            ts,
            clock_value as clockValue,
            clock_name as clockName
          from clock_snapshot
          where
            snapshot_id = 0 AND
            clock_name in ('REALTIME', 'REALTIME_COARSE')
          `;
      const result = await assertExists(this.engine).query(query);
      const it = result.iter({
        ts: LONG,
        clockValue: LONG,
        clockName: STR,
      });

      let snapshot = {
        clockName: '',
        ts: Time.ZERO,
        clockValue: Time.ZERO,
      };

      // Find the most suitable snapshot
      for (let row = 0; it.valid(); it.next(), row++) {
        if (it.clockName === 'REALTIME') {
          snapshot = {
            clockName: it.clockName,
            ts: Time.fromRaw(it.ts),
            clockValue: Time.fromRaw(it.clockValue),
          };
          break;
        } else if (it.clockName === 'REALTIME_COARSE') {
          if (snapshot.clockName !== 'REALTIME') {
            snapshot = {
              clockName: it.clockName,
              ts: Time.fromRaw(it.ts),
              clockValue: Time.fromRaw(it.clockValue),
            };
          }
        }
      }

      // The max() is so the query returns NULL if the tz info doesn't exist.
      const queryTz = `select max(int_value) as tzOffMin from metadata
          where name = 'timezone_off_mins'`;
      const resTz = await assertExists(this.engine).query(queryTz);
      const tzOffMin = resTz.firstRow({tzOffMin: NUM_NULL}).tzOffMin ?? 0;

      // This is the offset between the unix epoch and ts in the ts domain.
      // I.e. the value of ts at the time of the unix epoch - usually some large
      // negative value.
      const realtimeOffset = Time.sub(snapshot.ts, snapshot.clockValue);

      // Find the previous closest midnight from the trace start time.
      const utcOffset = Time.getLatestMidnight(
        globals.state.traceTime.start,
        realtimeOffset,
      );

      const traceTzOffset = Time.getLatestMidnight(
        globals.state.traceTime.start,
        Time.sub(realtimeOffset, Time.fromSeconds(tzOffMin * 60)));

      publishRealtimeOffset(realtimeOffset, utcOffset, traceTzOffset);
    }

    globals.dispatch(Actions.sortThreadTracks({}));
    globals.dispatch(Actions.maybeExpandOnlyTrackGroup({}));

    await this.selectFirstHeapProfile();
    if (PERF_SAMPLE_FLAG.get()) {
      await this.selectPerfSample();
    }

    const pendingDeeplink = globals.state.pendingDeeplink;
    if (pendingDeeplink !== undefined) {
      globals.dispatch(Actions.clearPendingDeeplink({}));
      await this.selectPendingDeeplink(pendingDeeplink);
      if (pendingDeeplink.visStart !== undefined &&
          pendingDeeplink.visEnd !== undefined) {
        this.zoomPendingDeeplink(
          pendingDeeplink.visStart, pendingDeeplink.visEnd);
      }
      if (pendingDeeplink.query !== undefined) {
        addQueryResultsTab({
          query: pendingDeeplink.query,
          title: 'Deeplink Query',
        });
      }
    }

    // If the trace was shared via a permalink, it might already have a
    // selection. Emit onSelectionChanged to ensure that the components (like
    // current selection details) react to it.
    if (globals.state.currentSelection !== null) {
      onSelectionChanged(globals.state.currentSelection, true);
    }

    globals.dispatch(Actions.maybeExpandOnlyTrackGroup({}));

    // Trace Processor doesn't support the reliable range feature for JSON
    // traces.
    if (!isJsonTrace && ENABLE_CHROME_RELIABLE_RANGE_ANNOTATION_FLAG.get()) {
      const reliableRangeStart = await computeTraceReliableRangeStart(engine);
      if (reliableRangeStart > 0) {
        globals.dispatch(Actions.addAutomaticNote({
          timestamp: reliableRangeStart,
          color: '#ff0000',
          text: 'Reliable Range Start',
        }));
      }
    }

    return engineMode;
  }

  private async selectPerfSample() {
    const query = `select upid
        from perf_sample
        join thread using (utid)
        where callsite_id is not null
        order by ts desc limit 1`;
    const profile = await assertExists(this.engine).query(query);
    if (profile.numRows() !== 1) return;
    const row = profile.firstRow({upid: NUM});
    const upid = row.upid;
    const leftTs = globals.state.traceTime.start;
    const rightTs = globals.state.traceTime.end;
    globals.dispatch(Actions.selectPerfSamples(
      {id: 0, upid, leftTs, rightTs, type: ProfileType.PERF_SAMPLE}));
  }

  private async selectFirstHeapProfile() {
    const query = `select * from (
      select
        min(ts) AS ts,
        'heap_profile:' || group_concat(distinct heap_name) AS type,
        upid
      from heap_profile_allocation
      group by upid
      union
      select distinct graph_sample_ts as ts, 'graph' as type, upid
      from heap_graph_object)
      order by ts limit 1`;
    const profile = await assertExists(this.engine).query(query);
    if (profile.numRows() !== 1) return;
    const row = profile.firstRow({ts: LONG, type: STR, upid: NUM});
    const ts = Time.fromRaw(row.ts);
    let profType = row.type;
    if (profType == 'heap_profile:libc.malloc,com.android.art') {
      profType = 'heap_profile:com.android.art,libc.malloc';
    }
    const type = profileType(profType);
    const upid = row.upid;
    globals.dispatch(Actions.selectHeapProfile({id: 0, upid, ts, type}));
  }

  private async selectPendingDeeplink(link: PendingDeeplinkState) {
    const conditions = [];
    const {ts, dur} = link;

    if (ts !== undefined) {
      conditions.push(`ts = ${ts}`);
    }
    if (dur !== undefined) {
      conditions.push(`dur = ${dur}`);
    }

    if (conditions.length === 0) {
      return;
    }

    const query = `
      select
        id,
        track_id as traceProcessorTrackId,
        type
      from slice
      where ${conditions.join(' and ')}
    ;`;


    const result = await assertExists(this.engine).query(query);
    if (result.numRows() > 0) {
      const row = result.firstRow({
        id: NUM,
        traceProcessorTrackId: NUM,
        type: STR,
      });

      const id = row.traceProcessorTrackId;
      const trackKey = globals.trackManager.trackKeyByTrackId.get(id);
      if (trackKey === undefined) {
        return;
      }
      globals.makeSelection(Actions.selectChromeSlice({
        id: row.id,
        trackKey,
        table: '',
        scroll: true,
      }));
    }
  }

  private async listTracks() {
    this.updateStatus('Loading tracks');
    const engine = assertExists<Engine>(this.engine);
    const actions = await decideTracks(engine);
    globals.dispatchMultiple(actions);
  }

  // Show the list of default tabs, but don't make them active!
  private decideTabs() {
    for (const tabUri of globals.tabManager.defaultTabs) {
      globals.dispatch(Actions.showTab({uri: tabUri}));
    }
  }

  private async listThreads() {
    this.updateStatus('Reading thread list');
    const query = `select
        utid,
        tid,
        pid,
        ifnull(thread.name, '') as threadName,
        ifnull(
          case when length(process.name) > 0 then process.name else null end,
          thread.name) as procName,
        process.cmdline as cmdline
        from (select * from thread order by upid) as thread
        left join (select * from process order by upid) as process
        using(upid)`;
    const result = await assertExists(this.engine).query(query);
    const threads: ThreadDesc[] = [];
    const it = result.iter({
      utid: NUM,
      tid: NUM,
      pid: NUM_NULL,
      threadName: STR,
      procName: STR_NULL,
      cmdline: STR_NULL,
    });
    for (; it.valid(); it.next()) {
      const utid = it.utid;
      const tid = it.tid;
      const pid = it.pid === null ? undefined : it.pid;
      const threadName = it.threadName;
      const procName = it.procName === null ? undefined : it.procName;
      const cmdline = it.cmdline === null ? undefined : it.cmdline;
      threads.push({utid, tid, threadName, pid, procName, cmdline});
    }
    publishThreads(threads);
  }

  private async loadTimelineOverview(trace: Span<time, duration>) {
    clearOverviewData();
    const engine = assertExists<Engine>(this.engine);
    const stepSize = Duration.max(1n, trace.duration / 100n);
    const hasSchedSql = 'select ts from sched limit 1';
    const hasSchedOverview = (await engine.query(hasSchedSql)).numRows() > 0;
    if (hasSchedOverview) {
      const stepPromises = [];
      for (let start = trace.start; start < trace.end;
        start = Time.add(start, stepSize)) {
        const progress = start - trace.start;
        const ratio = Number(progress) / Number(trace.duration);
        this.updateStatus(
          'Loading overview ' +
            `${Math.round(ratio * 100)}%`);
        const end = Time.add(start, stepSize);
        // The (async() => {})() queues all the 100 async promises in one batch.
        // Without that, we would wait for each step to be rendered before
        // kicking off the next one. That would interleave an animation frame
        // between each step, slowing down significantly the overall process.
        stepPromises.push((async () => {
          const schedResult = await engine.query(
            `select cast(sum(dur) as float)/${
              stepSize} as load, cpu from sched ` +
              `where ts >= ${start} and ts < ${end} and utid != 0 ` +
              'group by cpu order by cpu');
          const schedData: {[key: string]: QuantizedLoad} = {};
          const it = schedResult.iter({load: NUM, cpu: NUM});
          for (; it.valid(); it.next()) {
            const load = it.load;
            const cpu = it.cpu;
            schedData[cpu] = {start, end, load};
          }
          publishOverviewData(schedData);
        })());
      }  // for(start = ...)
      await Promise.all(stepPromises);
      return;
    }  // if (hasSchedOverview)

    // Slices overview.
    const sliceResult = await engine.query(`select
           bucket,
           upid,
           ifnull(sum(utid_sum) / cast(${stepSize} as float), 0) as load
         from thread
         inner join (
           select
             ifnull(cast((ts - ${trace.start})/${
  stepSize} as int), 0) as bucket,
             sum(dur) as utid_sum,
             utid
           from slice
           inner join thread_track on slice.track_id = thread_track.id
           group by bucket, utid
         ) using(utid)
         where upid is not null
         group by bucket, upid`);

    const slicesData: {[key: string]: QuantizedLoad[]} = {};
    const it = sliceResult.iter({bucket: LONG, upid: NUM, load: NUM});
    for (; it.valid(); it.next()) {
      const bucket = it.bucket;
      const upid = it.upid;
      const load = it.load;

      const start = Time.add(trace.start, stepSize * bucket);
      const end = Time.add(start, stepSize);

      const upidStr = upid.toString();
      let loadArray = slicesData[upidStr];
      if (loadArray === undefined) {
        loadArray = slicesData[upidStr] = [];
      }
      loadArray.push({start, end, load});
    }
    publishOverviewData(slicesData);
  }

  private async cacheCurrentTrace(): Promise<string> {
    const engine = assertExists(this.engine);
    const result = await engine.query(`select str_value as uuid from metadata
                  where name = 'trace_uuid'`);
    if (result.numRows() === 0) {
      // One of the cases covered is an empty trace.
      return '';
    }
    const traceUuid = result.firstRow({uuid: STR}).uuid;
    const engineConfig = assertExists(globals.state.engine);
    assertTrue(engineConfig.id === this.engineId);
    if (!(await cacheTrace(engineConfig.source, traceUuid))) {
      // If the trace is not cacheable (cacheable means it has been opened from
      // URL or RPC) only append '?local_cache_key' to the URL, without the
      // local_cache_key value. Doing otherwise would cause an error if the tab
      // is discarded or the user hits the reload button because the trace is
      // not in the cache.
      return '';
    }
    return traceUuid;
  }

  async initialiseHelperViews() {
    const engine = assertExists<Engine>(this.engine);

    this.updateStatus('Creating annotation counter track table');
    // Create the helper tables for all the annotations related data.
    // NULL in min/max means "figure it out per track in the usual way".
    await engine.query(`
      CREATE TABLE annotation_counter_track(
        id INTEGER PRIMARY KEY,
        name STRING,
        __metric_name STRING,
        upid INTEGER,
        min_value DOUBLE,
        max_value DOUBLE
      );
    `);
    this.updateStatus('Creating annotation slice track table');
    await engine.query(`
      CREATE TABLE annotation_slice_track(
        id INTEGER PRIMARY KEY,
        name STRING,
        __metric_name STRING,
        upid INTEGER,
        group_name STRING
      );
    `);

    this.updateStatus('Creating annotation counter table');
    await engine.query(`
      CREATE TABLE annotation_counter(
        id BIGINT,
        track_id INT,
        ts BIGINT,
        value DOUBLE,
        PRIMARY KEY (track_id, ts)
      ) WITHOUT ROWID;
    `);
    this.updateStatus('Creating annotation slice table');
    await engine.query(`
      CREATE TABLE annotation_slice(
        id INTEGER PRIMARY KEY,
        track_id INT,
        ts BIGINT,
        dur BIGINT,
        thread_dur BIGINT,
        depth INT,
        cat STRING,
        name STRING,
        UNIQUE(track_id, ts)
      );
    `);


    const availableMetrics = [];
    const metricsResult = await engine.query('select name from trace_metrics');
    for (const it = metricsResult.iter({name: STR}); it.valid(); it.next()) {
      availableMetrics.push(it.name);
    }

    const availableMetricsSet = new Set<string>(availableMetrics);
    for (const [flag, metric] of FLAGGED_METRICS) {
      if (!flag.get() || !availableMetricsSet.has(metric)) {
        continue;
      }

      this.updateStatus(`Computing ${metric} metric`);
      try {
        // We don't care about the actual result of metric here as we are just
        // interested in the annotation tracks.
        await engine.computeMetric([metric], 'proto');
      } catch (e) {
        if (e instanceof QueryError) {
          publishMetricError('MetricError: ' + e.message);
          continue;
        } else {
          throw e;
        }
      }

      this.updateStatus(`Inserting data for ${metric} metric`);
      try {
        const result = await engine.query(`pragma table_info(${metric}_event)`);
        let hasSliceName = false;
        let hasDur = false;
        let hasUpid = false;
        let hasValue = false;
        let hasGroupName = false;
        const it = result.iter({name: STR});
        for (; it.valid(); it.next()) {
          const name = it.name;
          hasSliceName = hasSliceName || name === 'slice_name';
          hasDur = hasDur || name === 'dur';
          hasUpid = hasUpid || name === 'upid';
          hasValue = hasValue || name === 'value';
          hasGroupName = hasGroupName || name === 'group_name';
        }

        const upidColumnSelect = hasUpid ? 'upid' : '0 AS upid';
        const upidColumnWhere = hasUpid ? 'upid' : '0';
        const groupNameColumn =
          hasGroupName ? 'group_name' : 'NULL AS group_name';
        if (hasSliceName && hasDur) {
          await engine.query(`
            INSERT INTO annotation_slice_track(
              name, __metric_name, upid, group_name)
            SELECT DISTINCT
              track_name,
              '${metric}' as metric_name,
              ${upidColumnSelect},
              ${groupNameColumn}
            FROM ${metric}_event
            WHERE track_type = 'slice'
          `);
          await engine.query(`
            INSERT INTO annotation_slice(
              track_id, ts, dur, thread_dur, depth, cat, name
            )
            SELECT
              t.id AS track_id,
              ts,
              dur,
              NULL as thread_dur,
              0 AS depth,
              a.track_name as cat,
              slice_name AS name
            FROM ${metric}_event a
            JOIN annotation_slice_track t
            ON a.track_name = t.name AND t.__metric_name = '${metric}'
            ORDER BY t.id, ts
          `);
        }

        if (hasValue) {
          const minMax = await engine.query(`
            SELECT
              IFNULL(MIN(value), 0) as minValue,
              IFNULL(MAX(value), 0) as maxValue
            FROM ${metric}_event
            WHERE ${upidColumnWhere} != 0`);
          const row = minMax.firstRow({minValue: NUM, maxValue: NUM});
          await engine.query(`
            INSERT INTO annotation_counter_track(
              name, __metric_name, min_value, max_value, upid)
            SELECT DISTINCT
              track_name,
              '${metric}' as metric_name,
              CASE ${upidColumnWhere} WHEN 0 THEN NULL ELSE ${row.minValue} END,
              CASE ${upidColumnWhere} WHEN 0 THEN NULL ELSE ${row.maxValue} END,
              ${upidColumnSelect}
            FROM ${metric}_event
            WHERE track_type = 'counter'
          `);
          await engine.query(`
            INSERT INTO annotation_counter(id, track_id, ts, value)
            SELECT
              -1 as id,
              t.id AS track_id,
              ts,
              value
            FROM ${metric}_event a
            JOIN annotation_counter_track t
            ON a.track_name = t.name AND t.__metric_name = '${metric}'
            ORDER BY t.id, ts
          `);
        }
      } catch (e) {
        if (e instanceof QueryError) {
          publishMetricError('MetricError: ' + e.message);
        } else {
          throw e;
        }
      }
    }
  }

  private updateStatus(msg: string): void {
    globals.dispatch(Actions.updateStatus({
      msg,
      timestamp: Date.now() / 1000,
    }));
  }

  private zoomPendingDeeplink(visStart: string, visEnd: string) {
    const visualStart = Time.fromRaw(BigInt(visStart));
    const visualEnd = Time.fromRaw(BigInt(visEnd));
    const traceTime = globals.stateTraceTimeTP();

    if (!(visualStart < visualEnd && traceTime.start <= visualStart &&
          visualEnd <= traceTime.end)) {
      return;
    }

    const res = (visualEnd - visualStart) / 1000n;

    globals.dispatch(Actions.setVisibleTraceTime({
      start: visualStart,
      end: visualEnd,
      resolution: BigintMath.max(res, 1n),
      lastUpdate: Date.now() / 1000,
    }));
  }
}

async function computeFtraceBounds(engine: Engine): Promise<TimeSpan|null> {
  const result = await engine.query(`
    SELECT min(ts) as start, max(ts) as end FROM ftrace_event;
  `);
  const {start, end} = result.firstRow({start: LONG_NULL, end: LONG_NULL});
  if (start !== null && end !== null) {
    return new TimeSpan(Time.fromRaw(start), Time.fromRaw(end));
  }
  return null;
}

async function computeTraceReliableRangeStart(engine: Engine): Promise<time> {
  const result =
    await engine.query(`SELECT RUN_METRIC('chrome/chrome_reliable_range.sql');
       SELECT start FROM chrome_reliable_range`);
  const bounds = result.firstRow({start: LONG});
  return Time.fromRaw(bounds.start);
}

async function computeVisibleTime(
  traceStart: time, traceEnd: time, isJsonTrace: boolean, engine: Engine):
    Promise<Span<HighPrecisionTime>> {
  // if we have non-default visible state, update the visible time to it
  const previousVisibleState = globals.stateVisibleTime();
  const defaultTraceSpan =
      new TimeSpan(defaultTraceTime.start, defaultTraceTime.end);
  if (!(previousVisibleState.start === defaultTraceSpan.start &&
        previousVisibleState.end === defaultTraceSpan.end) &&
      (previousVisibleState.start >= traceStart &&
       previousVisibleState.end <= traceEnd)) {
    return HighPrecisionTimeSpan.fromTime(
      previousVisibleState.start, previousVisibleState.end);
  }

  // initialise visible time to the trace time bounds
  let visibleStart = traceStart;
  let visibleEnd = traceEnd;

  // compare start and end with metadata computed by the trace processor
  const mdTime = await engine.getTracingMetadataTimeBounds();
  // make sure the bounds hold
  if (Time.max(visibleStart, mdTime.start) < Time.min(visibleEnd, mdTime.end)) {
    visibleStart = Time.max(visibleStart, mdTime.start);
    visibleEnd = Time.min(visibleEnd, mdTime.end);
  }

  // Trace Processor doesn't support the reliable range feature for JSON
  // traces.
  if (!isJsonTrace && ENABLE_CHROME_RELIABLE_RANGE_ZOOM_FLAG.get()) {
    const reliableRangeStart = await computeTraceReliableRangeStart(engine);
    visibleStart = Time.max(visibleStart, reliableRangeStart);
  }

  const ftraceBounds = await computeFtraceBounds(engine);
  if (ftraceBounds !== null) {
    visibleStart = ftraceBounds.start;
  }
  return HighPrecisionTimeSpan.fromTime(visibleStart, visibleEnd);
}
