// 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 '../tracks/all_controller';

import * as uuidv4 from 'uuid/v4';

import {assertExists, assertTrue} from '../base/logging';
import {
  Actions,
  AddTrackArgs,
  DeferredAction,
} from '../common/actions';
import {Engine} from '../common/engine';
import {HttpRpcEngine} from '../common/http_rpc_engine';
import {NUM, NUM_NULL, rawQueryToRows, STR_NULL} from '../common/protos';
import {
  EngineMode,
  SCROLLING_TRACK_GROUP,
} from '../common/state';
import {toNs, toNsCeil, toNsFloor} from '../common/time';
import {TimeSpan} from '../common/time';
import {
  createWasmEngine,
  destroyWasmEngine,
  WasmEngineProxy
} from '../common/wasm_engine_proxy';
import {QuantizedLoad, ThreadDesc} from '../frontend/globals';
import {ANDROID_LOGS_TRACK_KIND} from '../tracks/android_log/common';
import {ASYNC_SLICE_TRACK_KIND} from '../tracks/async_slices/common';
import {SLICE_TRACK_KIND} from '../tracks/chrome_slices/common';
import {CPU_FREQ_TRACK_KIND} from '../tracks/cpu_freq/common';
import {CPU_PROFILE_TRACK_KIND} from '../tracks/cpu_profile/common';
import {CPU_SLICE_TRACK_KIND} from '../tracks/cpu_slices/common';
import {GPU_FREQ_TRACK_KIND} from '../tracks/gpu_freq/common';
import {HEAP_PROFILE_TRACK_KIND} from '../tracks/heap_profile/common';
import {
  PROCESS_SCHEDULING_TRACK_KIND
} from '../tracks/process_scheduling/common';
import {PROCESS_SUMMARY_TRACK} from '../tracks/process_summary/common';
import {THREAD_STATE_TRACK_KIND} from '../tracks/thread_state/common';

import {
  CpuAggregationController
} from './aggregation/cpu_aggregation_controller';
import {
  ThreadAggregationController
} from './aggregation/thread_aggregation_controller';
import {Child, Children, Controller} from './controller';
import {
  CpuProfileController,
  CpuProfileControllerArgs
} from './cpu_profile_controller';
import {globals} from './globals';
import {
  HeapProfileController,
  HeapProfileControllerArgs
} from './heap_profile_controller';
import {LoadingManager} from './loading_manager';
import {LogsController} from './logs_controller';
import {QueryController, QueryControllerArgs} from './query_controller';
import {SearchController} from './search_controller';
import {
  SelectionController,
  SelectionControllerArgs
} from './selection_controller';
import {
  TraceBufferStream,
  TraceFileStream,
  TraceHttpStream,
  TraceStream
} from './trace_stream';
import {TrackControllerArgs, trackControllerRegistry} from './track_controller';

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

interface ThreadSliceTrack {
  maxDepth: number;
  trackId: number;
}

// 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;
  }

  onDestroy() {
    if (this.engine instanceof WasmEngineProxy) {
      destroyWasmEngine(this.engine.id);
    }
  }

  run() {
    const engineCfg = assertExists(globals.state.engines[this.engineId]);
    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);
        assertTrue(engineCfg.ready);
        const childControllers: Children = [];

        // Create a TrackController for each track.
        for (const trackId of Object.keys(globals.state.tracks)) {
          const trackCfg = globals.state.tracks[trackId];
          if (trackCfg.engineId !== this.engineId) continue;
          if (!trackControllerRegistry.has(trackCfg.kind)) continue;
          const trackCtlFactory = trackControllerRegistry.get(trackCfg.kind);
          const trackArgs: TrackControllerArgs = {trackId, engine};
          childControllers.push(Child(trackId, trackCtlFactory, trackArgs));
        }

        // Create a QueryController for each query.
        for (const queryId of Object.keys(globals.state.queries)) {
          const queryArgs: QueryControllerArgs = {queryId, engine};
          childControllers.push(Child(queryId, QueryController, queryArgs));
        }

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

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

        const heapProfileArgs: HeapProfileControllerArgs = {engine};
        childControllers.push(
            Child('heapProfile', HeapProfileController, heapProfileArgs));
        childControllers.push(Child(
            'cpu_aggregation',
            CpuAggregationController,
            {engine, kind: 'cpu_aggregation'}));
        childControllers.push(Child(
            'thread_aggregation',
            ThreadAggregationController,
            {engine, kind: 'thread_state_aggregation'}));
        childControllers.push(Child('search', SearchController, {
          engine,
          app: globals,
        }));

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

        return childControllers;

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

  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;
    }
    if (useRpc) {
      console.log('Opening trace using native accelerator over HTTP+RPC');
      engineMode = 'HTTP_RPC';
      const engine =
          new HttpRpcEngine(this.engineId, LoadingManager.getInstance);
      engine.errorHandler = (err) => {
        globals.dispatch(
            Actions.setEngineFailed({mode: 'HTTP_RPC', failure: `${err}`}));
        throw err;
      };
      this.engine = engine;
    } else {
      console.log('Opening trace using built-in WASM engine');
      engineMode = 'WASM';
      this.engine = new WasmEngineProxy(
          this.engineId,
          createWasmEngine(this.engineId),
          LoadingManager.getInstance);
    }

    globals.dispatch(Actions.setEngineReady({
      engineId: this.engineId,
      ready: false,
      mode: engineMode,
    }));
    const engineCfg = assertExists(globals.state.engines[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();
    }

    const traceTime = await this.engine.getTraceTimeBounds();
    const traceTimeState = {
      startSec: traceTime.start,
      endSec: traceTime.end,
    };
    const actions: DeferredAction[] = [
      Actions.setTraceTime(traceTimeState),
      Actions.navigate({route: '/viewer'}),
    ];

    // We don't know the resolution at this point. However this will be
    // replaced in 50ms so a guess is fine.
    const resolution = (traceTime.end - traceTime.start) / 1000;
    actions.push(Actions.setVisibleTraceTime(
        {...traceTimeState, lastUpdate: Date.now() / 1000, resolution}));

    globals.dispatchMultiple(actions);

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

    {
      // 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();
      }
    }

    await this.listThreads();
    await this.loadTimelineOverview(traceTime);
    return engineMode;
  }

  private async listTracks() {
    this.updateStatus('Loading tracks');

    const engine = assertExists<Engine>(this.engine);
    const numGpus = await engine.getNumberOfGpus();
    const tracksToAdd: AddTrackArgs[] = [];

    const maxCpuFreq = await engine.query(`
      select max(value)
      from counter c
      inner join cpu_counter_track t on c.track_id = t.id
      where name = 'cpufreq';
    `);

    const cpus = await engine.getCpus();

    for (const cpu of cpus) {
      tracksToAdd.push({
        engineId: this.engineId,
        kind: CPU_SLICE_TRACK_KIND,
        name: `Cpu ${cpu}`,
        trackGroup: SCROLLING_TRACK_GROUP,
        config: {
          cpu,
        }
      });
    }

    for (const cpu of cpus) {
      // Only add a cpu freq track if we have
      // cpu freq data.
      // TODO(taylori): Find a way to display cpu idle
      // events even if there are no cpu freq events.
      const cpuFreqIdle = await engine.query(`
        select
          id as cpu_freq_id,
          (
            select id
            from cpu_counter_track
            where name = 'cpuidle'
            and cpu = ${cpu}
            limit 1
          ) as cpu_idle_id
        from cpu_counter_track
        where name = 'cpufreq' and cpu = ${cpu}
        limit 1;
      `);
      if (cpuFreqIdle.numRecords > 0) {
        const freqTrackId = +cpuFreqIdle.columns[0].longValues![0];

        const idleTrackExists: boolean = !cpuFreqIdle.columns[1].isNulls![0];
        const idleTrackId = idleTrackExists ?
            +cpuFreqIdle.columns[1].longValues![0] :
            undefined;

        tracksToAdd.push({
          engineId: this.engineId,
          kind: CPU_FREQ_TRACK_KIND,
          name: `Cpu ${cpu} Frequency`,
          trackGroup: SCROLLING_TRACK_GROUP,
          config: {
            cpu,
            maximumValue: +maxCpuFreq.columns[0].doubleValues![0],
            freqTrackId,
            idleTrackId,
          }
        });
      }
    }

    const rawGlobalAsyncTracks = await engine.query(`
      SELECT
        t.name,
        t.track_ids,
        MAX(experimental_slice_layout.layout_depth) as max_depth
      FROM (
        SELECT name, GROUP_CONCAT(track.id) AS track_ids
        FROM track
        WHERE track.type = "track"
        GROUP BY name
      ) AS t CROSS JOIN experimental_slice_layout
      WHERE t.track_ids = experimental_slice_layout.filter_track_ids
      GROUP BY t.track_ids;
    `);
    for (let i = 0; i < rawGlobalAsyncTracks.numRecords; i++) {
      const name = rawGlobalAsyncTracks.columns[0].stringValues![i];
      const rawTrackIds = rawGlobalAsyncTracks.columns[1].stringValues![i];
      const trackIds = rawTrackIds.split(',').map(v => Number(v));
      const maxDepth = +rawGlobalAsyncTracks.columns[2].longValues![i];
      const track = {
        engineId: this.engineId,
        kind: ASYNC_SLICE_TRACK_KIND,
        trackGroup: SCROLLING_TRACK_GROUP,
        name,
        config: {
          maxDepth,
          trackIds,
        },
      };
      tracksToAdd.push(track);
    }

    const upidToProcessTracks = new Map();
    const rawProcessTracks = await engine.query(`
      SELECT
        pt.upid,
        pt.name,
        pt.track_ids,
        MAX(experimental_slice_layout.layout_depth) as max_depth
      FROM (
        SELECT upid, name, GROUP_CONCAT(process_track.id) AS track_ids
        FROM process_track GROUP BY upid, name
      ) AS pt CROSS JOIN experimental_slice_layout
      WHERE pt.track_ids = experimental_slice_layout.filter_track_ids
      GROUP BY pt.track_ids;
    `);
    for (let i = 0; i < rawProcessTracks.numRecords; i++) {
      const upid = +rawProcessTracks.columns[0].longValues![i];
      const name = rawProcessTracks.columns[1].stringValues![i];
      const rawTrackIds = rawProcessTracks.columns[2].stringValues![i];
      const trackIds = rawTrackIds.split(',').map(v => Number(v));
      const maxDepth = +rawProcessTracks.columns[3].longValues![i];
      const track = {
        engineId: this.engineId,
        kind: 'AsyncSliceTrack',
        name,
        config: {
          maxDepth,
          trackIds,
        },
      };
      const tracks = upidToProcessTracks.get(upid);
      if (tracks) {
        tracks.push(track);
      } else {
        upidToProcessTracks.set(upid, [track]);
      }
    }

    const heapProfiles = await engine.query(`
      select distinct(upid) from heap_profile_allocation
      union
      select distinct(upid) from heap_graph_object`);

    const heapUpids: Set<number> = new Set();
    for (let i = 0; i < heapProfiles.numRecords; i++) {
      const upid = heapProfiles.columns[0].longValues![i];
      heapUpids.add(+upid);
    }

    const maxGpuFreq = await engine.query(`
      select max(value)
      from counter c
      inner join gpu_counter_track t on c.track_id = t.id
      where name = 'gpufreq';
    `);

    for (let gpu = 0; gpu < numGpus; gpu++) {
      // Only add a gpu freq track if we have
      // gpu freq data.
      const freqExists = await engine.query(`
        select id
        from gpu_counter_track
        where name = 'gpufreq' and gpu_id = ${gpu}
        limit 1;
      `);
      if (freqExists.numRecords > 0) {
        tracksToAdd.push({
          engineId: this.engineId,
          kind: GPU_FREQ_TRACK_KIND,
          name: `Gpu ${gpu} Frequency`,
          trackGroup: SCROLLING_TRACK_GROUP,
          config: {
            gpu,
            trackId: +freqExists.columns[0].longValues![0],
            maximumValue: +maxGpuFreq.columns[0].doubleValues![0],
          }
        });
      }
    }

    // Add global or GPU counter tracks that are not bound to any pid/tid.
    const globalCounters = await engine.query(`
      select name, id
      from counter_track
      where type = 'counter_track'
      union
      select name, id
      from gpu_counter_track
      where name != 'gpufreq'
    `);
    for (let i = 0; i < globalCounters.numRecords; i++) {
      const name = globalCounters.columns[0].stringValues![i];
      const trackId = +globalCounters.columns[1].longValues![i];
      tracksToAdd.push({
        engineId: this.engineId,
        kind: 'CounterTrack',
        name,
        trackGroup: SCROLLING_TRACK_GROUP,
        config: {
          name,
          trackId,
        }
      });
    }

    interface CounterTrack {
      name: string;
      trackId: number;
      startTs?: number;
      endTs?: number;
    }

    const counterUtids = new Map<number, CounterTrack[]>();
    const threadCounters = await engine.query(`
      select thread_counter_track.name, utid, thread_counter_track.id,
      start_ts, end_ts from thread_counter_track join thread using(utid)
      where thread_counter_track.name not in ('time_in_state')
    `);
    for (let i = 0; i < threadCounters.numRecords; i++) {
      const name = threadCounters.columns[0].stringValues![i];
      const utid = +threadCounters.columns[1].longValues![i];
      const trackId = +threadCounters.columns[2].longValues![i];
      let startTs = undefined;
      let endTs = undefined;
      if (!threadCounters.columns[3].isNulls![i]) {
        startTs = +threadCounters.columns[3].longValues![i] / 1e9;
      }
      if (!threadCounters.columns[4].isNulls![i]) {
        endTs = +threadCounters.columns[4].longValues![i] / 1e9;
      }

      const track: CounterTrack = {name, trackId, startTs, endTs};
      const el = counterUtids.get(utid);
      if (el === undefined) {
        counterUtids.set(utid, [track]);
      } else {
        el.push(track);
      }
    }

    const counterUpids = new Map<number, CounterTrack[]>();
    const processCounters = await engine.query(`
      select process_counter_track.name, upid, process_counter_track.id,
      start_ts, end_ts from process_counter_track join process using(upid)
    `);
    for (let i = 0; i < processCounters.numRecords; i++) {
      const name = processCounters.columns[0].stringValues![i];
      const upid = +processCounters.columns[1].longValues![i];
      const trackId = +processCounters.columns[2].longValues![i];
      let startTs = undefined;
      let endTs = undefined;
      if (!processCounters.columns[3].isNulls![i]) {
        startTs = +processCounters.columns[3].longValues![i] / 1e9;
      }
      if (!processCounters.columns[4].isNulls![i]) {
        endTs = +processCounters.columns[4].longValues![i] / 1e9;
      }

      const track: CounterTrack = {name, trackId, startTs, endTs};
      const el = counterUpids.get(upid);
      if (el === undefined) {
        counterUpids.set(upid, [track]);
      } else {
        el.push(track);
      }
    }

    // Local experiments shows getting maxDepth separately is ~2x faster than
    // joining with threads and processes.
    const maxDepthQuery = await engine.query(`
          select thread_track.utid, thread_track.id, max(depth) as maxDepth
          from slice
          inner join thread_track on slice.track_id = thread_track.id
          group by thread_track.id
        `);

    const utidToThreadTrack = new Map<number, ThreadSliceTrack>();
    for (let i = 0; i < maxDepthQuery.numRecords; i++) {
      const utid = maxDepthQuery.columns[0].longValues![i] as number;
      const trackId = maxDepthQuery.columns[1].longValues![i] as number;
      const maxDepth = maxDepthQuery.columns[2].longValues![i] as number;
      utidToThreadTrack.set(utid, {maxDepth, trackId});
    }

    // Return all threads
    // sorted by:
    //  total cpu time *for the whole parent process*
    //  upid
    //  utid
    const threadQuery = await engine.query(`
        select
          utid,
          tid,
          upid,
          pid,
          thread.name as threadName,
          process.name as processName,
          total_dur as totalDur,
          ifnull(has_sched, false) as hasSched,
          ifnull(has_cpu_samples, false) as hasCpuSamples
        from
          thread
          left join (select utid, count(1), true as has_sched
              from sched group by utid
          ) using(utid)
          left join (select utid, count(1), true as has_cpu_samples
              from cpu_profile_stack_sample group by utid
          ) using(utid)
          left join process using(upid)
          left join (select upid, sum(dur) as total_dur
              from sched join thread using(utid)
              group by upid
            ) using(upid)
          left join (select upid, sum(value) as total_cycles
              from android_thread_time_in_state_event
              group by upid
            ) using(upid)
        where utid != 0
        group by utid, upid
        order by total_dur desc, total_cycles desc, upid, utid`);

    const upidToUuid = new Map<number, string>();
    const utidToUuid = new Map<number, string>();
    const addTrackGroupActions: DeferredAction[] = [];

    for (const row of rawQueryToRows(threadQuery, {
           utid: NUM,
           upid: NUM_NULL,
           tid: NUM_NULL,
           pid: NUM_NULL,
           threadName: STR_NULL,
           processName: STR_NULL,
           totalDur: NUM_NULL,
           hasSched: NUM,
           hasCpuSamples: NUM,
         })) {
      const utid = row.utid;
      const tid = row.tid;
      const upid = row.upid;
      const pid = row.pid;
      const threadName = row.threadName;
      const processName = row.processName;
      const hasSchedEvents = !!row.totalDur;
      const threadHasSched = !!row.hasSched;
      const threadHasCpuSamples = !!row.hasCpuSamples;

      const threadTrack =
          utid === null ? undefined : utidToThreadTrack.get(utid);
      if (threadTrack === undefined &&
          (upid === null || counterUpids.get(upid) === undefined) &&
          counterUtids.get(utid) === undefined && !threadHasSched &&
          (upid === null || upid !== null && !heapUpids.has(upid))) {
        continue;
      }

      // Group by upid if present else by utid.
      let pUuid = upid === null ? utidToUuid.get(utid) : upidToUuid.get(upid);
      // These should only happen once for each track group.
      if (pUuid === undefined) {
        pUuid = uuidv4();
        const summaryTrackId = uuidv4();
        if (upid === null) {
          utidToUuid.set(utid, pUuid);
        } else {
          upidToUuid.set(upid, pUuid);
        }

        const pidForColor = pid || tid || upid || utid || 0;
        const kind = hasSchedEvents ? PROCESS_SCHEDULING_TRACK_KIND :
                                      PROCESS_SUMMARY_TRACK;

        tracksToAdd.push({
          id: summaryTrackId,
          engineId: this.engineId,
          kind,
          name: `${upid === null ? tid : pid} summary`,
          config: {pidForColor, upid, utid},
        });

        const name =
            getTrackName({utid, processName, pid, threadName, tid, upid});
        const addTrackGroup = Actions.addTrackGroup({
          engineId: this.engineId,
          summaryTrackId,
          name,
          id: pUuid,
          collapsed: !(upid !== null && heapUpids.has(upid)),
        });

        // If the track group contains a heap profile, it should be before all
        // other processes.
        if (upid !== null && heapUpids.has(upid)) {
          addTrackGroupActions.unshift(addTrackGroup);
        } else {
          addTrackGroupActions.push(addTrackGroup);
        }

        if (upid !== null) {
          if (heapUpids.has(upid)) {
            tracksToAdd.push({
              engineId: this.engineId,
              kind: HEAP_PROFILE_TRACK_KIND,
              name: `Heap Profile`,
              trackGroup: pUuid,
              config: {upid}
            });
          }

          const counterNames = counterUpids.get(upid);
          if (counterNames !== undefined) {
            counterNames.forEach(element => {
              tracksToAdd.push({
                engineId: this.engineId,
                kind: 'CounterTrack',
                name: element.name,
                trackGroup: pUuid,
                config: {
                  name: element.name,
                  trackId: element.trackId,
                  startTs: element.startTs,
                  endTs: element.endTs,
                }
              });
            });
          }

          if (upidToProcessTracks.has(upid)) {
            for (const track of upidToProcessTracks.get(upid)) {
              tracksToAdd.push(Object.assign(track, {trackGroup: pUuid}));
            }
          }
        }
      }
      const counterThreadNames = counterUtids.get(utid);
      if (counterThreadNames !== undefined) {
        counterThreadNames.forEach(element => {
          tracksToAdd.push({
            engineId: this.engineId,
            kind: 'CounterTrack',
            name: `${threadName} (${element.name})`,
            trackGroup: pUuid,
            config: {
              name: element.name,
              trackId: element.trackId,
              startTs: element.startTs,
              endTs: element.endTs,
            }
          });
        });
      }

      if (threadHasCpuSamples) {
        tracksToAdd.push({
          engineId: this.engineId,
          kind: CPU_PROFILE_TRACK_KIND,
          name: `${threadName} (CPU Stack Samples)`,
          trackGroup: pUuid,
          config: {utid},
        });
      }

      if (threadHasSched) {
        tracksToAdd.push({
          engineId: this.engineId,
          kind: THREAD_STATE_TRACK_KIND,
          name: getTrackName({utid, tid, threadName}),
          trackGroup: pUuid,
          config: {utid}
        });
      }

      if (threadTrack !== undefined) {
        tracksToAdd.push({
          engineId: this.engineId,
          kind: SLICE_TRACK_KIND,
          name: getTrackName({utid, tid, threadName}),
          trackGroup: pUuid,
          config:
              {maxDepth: threadTrack.maxDepth, trackId: threadTrack.trackId},
        });
      }
    }

    const logCount = await engine.query(`select count(1) from android_logs`);
    if (logCount.columns[0].longValues![0] > 0) {
      tracksToAdd.push({
        engineId: this.engineId,
        kind: ANDROID_LOGS_TRACK_KIND,
        name: 'Android logs',
        trackGroup: SCROLLING_TRACK_GROUP,
        config: {}
      });
    }

    const annotationSliceRows = await engine.query(`
      SELECT id, name, upid FROM annotation_slice_track`);
    for (let i = 0; i < annotationSliceRows.numRecords; i++) {
      const id = annotationSliceRows.columns[0].longValues![i];
      const name = annotationSliceRows.columns[1].stringValues![i];
      const upid = annotationSliceRows.columns[2].longValues![i] as number;
      tracksToAdd.push({
        engineId: this.engineId,
        kind: SLICE_TRACK_KIND,
        name,
        trackGroup: upid === 0 ? SCROLLING_TRACK_GROUP : upidToUuid.get(upid),
        config: {
          maxDepth: 0,
          namespace: 'annotation',
          trackId: id,
        },
      });
    }

    const annotationCounterRows = await engine.query(`
      SELECT id, name, upid, min_value, max_value
      FROM annotation_counter_track`);
    for (let i = 0; i < annotationCounterRows.numRecords; i++) {
      const id = annotationCounterRows.columns[0].longValues![i];
      const name = annotationCounterRows.columns[1].stringValues![i];
      const upid = annotationCounterRows.columns[2].longValues![i] as number;
      const minimumValue = annotationCounterRows.columns[3].isNulls![i] ?
          undefined :
          annotationCounterRows.columns[3].doubleValues![i];
      const maximumValue = annotationCounterRows.columns[4].isNulls![i] ?
          undefined :
          annotationCounterRows.columns[4].doubleValues![i];
      tracksToAdd.push({
        engineId: this.engineId,
        kind: 'CounterTrack',
        name,
        trackGroup: upid === 0 ? SCROLLING_TRACK_GROUP : upidToUuid.get(upid),
        config: {
          name,
          namespace: 'annotation',
          trackId: id,
          minimumValue,
          maximumValue,
        }
      });
    }

    addTrackGroupActions.push(Actions.addTracks({tracks: tracksToAdd}));
    globals.dispatchMultiple(addTrackGroupActions);
  }

  private async listThreads() {
    this.updateStatus('Reading thread list');
    const sqlQuery = `select utid, tid, pid, thread.name,
        ifnull(
          case when length(process.name) > 0 then process.name else null end,
          thread.name)
        from (select * from thread order by upid) as thread
        left join (select * from process order by upid) as process
        using(upid)`;
    const threadRows = await assertExists(this.engine).query(sqlQuery);
    const threads: ThreadDesc[] = [];
    for (let i = 0; i < threadRows.numRecords; i++) {
      const utid = threadRows.columns[0].longValues![i] as number;
      const tid = threadRows.columns[1].longValues![i] as number;
      const pid = threadRows.columns[2].longValues![i] as number;
      const threadName = threadRows.columns[3].stringValues![i];
      const procName = threadRows.columns[4].stringValues![i];
      threads.push({utid, tid, threadName, pid, procName});
    }  // for (record ...)
    globals.publish('Threads', threads);
  }

  private async loadTimelineOverview(traceTime: TimeSpan) {
    const engine = assertExists<Engine>(this.engine);
    const numSteps = 100;
    const stepSec = traceTime.duration / numSteps;
    let hasSchedOverview = false;
    for (let step = 0; step < numSteps; step++) {
      this.updateStatus(
          'Loading overview ' +
          `${Math.round((step + 1) / numSteps * 1000) / 10}%`);
      const startSec = traceTime.start + step * stepSec;
      const startNs = toNsFloor(startSec);
      const endSec = startSec + stepSec;
      const endNs = toNsCeil(endSec);

      // Sched overview.
      const schedRows = await engine.query(
          `select sum(dur)/${stepSec}/1e9, cpu from sched ` +
          `where ts >= ${startNs} and ts < ${endNs} and utid != 0 ` +
          'group by cpu order by cpu');
      const schedData: {[key: string]: QuantizedLoad} = {};
      for (let i = 0; i < schedRows.numRecords; i++) {
        const load = schedRows.columns[0].doubleValues![i];
        const cpu = schedRows.columns[1].longValues![i] as number;
        schedData[cpu] = {startSec, endSec, load};
        hasSchedOverview = true;
      }  // for (record ...)
      globals.publish('OverviewData', schedData);
    }  // for (step ...)

    if (hasSchedOverview) {
      return;
    }

    // Slices overview.
    const traceStartNs = toNs(traceTime.start);
    const stepSecNs = toNs(stepSec);
    const sliceSummaryQuery = await engine.query(`select
           bucket,
           upid,
           sum(utid_sum) / cast(${stepSecNs} as float) as upid_sum
         from thread
         inner join (
           select
             cast((ts - ${traceStartNs})/${stepSecNs} as int) 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)
         group by bucket, upid`);

    const slicesData: {[key: string]: QuantizedLoad[]} = {};
    for (let i = 0; i < sliceSummaryQuery.numRecords; i++) {
      const bucket = sliceSummaryQuery.columns[0].longValues![i] as number;
      const upid = sliceSummaryQuery.columns[1].longValues![i] as number;
      const load = sliceSummaryQuery.columns[2].doubleValues![i];

      const startSec = traceTime.start + stepSec * bucket;
      const endSec = startSec + stepSec;

      const upidStr = upid.toString();
      let loadArray = slicesData[upidStr];
      if (loadArray === undefined) {
        loadArray = slicesData[upidStr] = [];
      }
      loadArray.push({startSec, endSec, load});
    }
    globals.publish('OverviewData', slicesData);
  }

  async initialiseHelperViews() {
    const engine = assertExists<Engine>(this.engine);
    this.updateStatus('Creating views');
    let event = 'sched_waking';
    const waking = await engine.query(
        `select * from instants where name = 'sched_waking' limit 1`);
    if (waking.numRecords === 0) {
      // Only use sched_wakeup if sched_waking is not in the trace.
      event = 'sched_wakeup';
    }
    await engine.query(`create view runnable AS
      select
        ts,
        lead(ts, 1, (select end_ts from trace_bounds))
          OVER(partition by ref order by ts) - ts as dur,
        ref as utid
      from instants
      where name = '${event}'`);

    // Get the first ts for each utid - whether a sched wakeup/waking
    // or sched event.
    await engine.query(`create view first_thread as
      select min(ts) as ts, utid from
      (select min(ts) as ts, utid from runnable group by utid
       UNION
      select min(ts) as ts,utid from sched group by utid)
      group by utid`);

    // Create an entry from first ts to either the first sched_wakeup/waking
    // or to the end if there are no sched wakeup/ings. This means we will
    // show all information we have even with no sched_wakeup/waking events.
    await engine.query(`create view fill as
      select first_thread.ts as ts,
      coalesce(min(runnable.ts), (select end_ts from trace_bounds)) -
      first_thread.ts as dur,
      first_thread.utid as utid
      from first_thread
      LEFT JOIN runnable using(utid) group by utid`);

    await engine.query(`create view full_runnable as
        select * from runnable UNION
        select * from fill`);

    await engine.query(`create virtual table thread_span
        using span_left_join(
          full_runnable partitioned utid,
          sched partitioned utid)`);

    this.updateStatus('Creating thread state table');
    // For performance reasons we need to create a table here.
    // Once b/145350531 is fixed this should be able to revert to a
    // view and we can recover the extra memory use.
    await engine.query(`create table thread_state as
      select ts, dur, utid, cpu,
      case when end_state is not null then 'Running'
      when lag(end_state) over ordered is not null
      then lag(end_state) over ordered else 'R'
      end as state
      from thread_span window ordered as
      (partition by utid order by ts)`);

    this.updateStatus('Creating thread state index');
    await engine.query(`create index utid_index on thread_state(utid)`);

    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
      );
    `);

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

    for (const metric
             of ['android_startup',
                 'android_ion',
                 'android_thread_time_in_state',
                 'android_surfaceflinger']) {
      this.updateStatus(`Computing ${metric} metric`);
      // We don't care about the actual result of metric here as we are just
      // interested in the annotation tracks.
      const metricResult = await engine.computeMetric([metric]);
      assertTrue(metricResult.error.length === 0);

      this.updateStatus(`Inserting data for ${metric} metric`);
      const result = await engine.query(`
        SELECT * FROM ${metric}_event LIMIT 1`);

      const hasSliceName =
          result.columnDescriptors.some(x => x.name === 'slice_name');
      const hasDur = result.columnDescriptors.some(x => x.name === 'dur');
      const hasUpid = result.columnDescriptors.some(x => x.name === 'upid');

      const upidColumnSelect = hasUpid ? 'upid' : '0 AS upid';
      const upidColumnWhere = hasUpid ? 'upid' : '0';
      if (hasSliceName && hasDur) {
        await engine.query(`
          INSERT INTO annotation_slice_track(name, __metric_name, upid)
          SELECT DISTINCT
            track_name,
            '${metric}' as metric_name,
            ${upidColumnSelect}
          FROM ${metric}_event
          WHERE track_type = 'slice'
        `);
        await engine.query(`
          INSERT INTO annotation_slice(id, track_id, ts, dur, depth, cat, name)
          SELECT
            row_number() over (order by ts) as id,
            t.id AS track_id,
            ts,
            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
        `);
      }

      const hasValue = result.columnDescriptors.some(x => x.name === 'value');
      if (hasValue) {
        const minMax = await engine.query(`
          SELECT MIN(value) as min_value, MAX(value) as max_value
          FROM ${metric}_event
          WHERE ${upidColumnWhere} != 0`);
        const min = minMax.columns[0].longValues![0] as number;
        const max = minMax.columns[1].longValues![0] as number;
        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 ${min} END,
            CASE ${upidColumnWhere} WHEN 0 THEN NULL ELSE ${max} 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
        `);
      }
    }
  }

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

function getTrackName(args: Partial<{
  utid: number,
  processName: string | null,
  pid: number | null,
  threadName: string | null,
  tid: number | null,
  upid: number | null
}>) {
  const {upid, utid, processName, threadName, pid, tid} = args;

  const hasUpid = upid !== undefined && upid !== null;
  const hasUtid = utid !== undefined && utid !== null;
  const hasProcessName = processName !== undefined && processName !== null;
  const hasThreadName = threadName !== undefined && threadName !== null;
  const hasTid = tid !== undefined && tid !== null;
  const hasPid = pid !== undefined && pid !== null;

  if (hasUpid && hasPid && hasProcessName) {
    return `${processName} ${pid}`;
  } else if (hasUpid && hasPid) {
    return `Process ${pid}`;
  } else if (hasThreadName && hasTid) {
    return `${threadName} ${tid}`;
  } else if (hasTid) {
    return `Thread ${tid}`;
  } else if (hasUpid) {
    return `upid: ${upid}`;
  } else if (hasUtid) {
    return `utid: ${utid}`;
  }
  return 'Unknown';
}
