// Copyright (C) 2019 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 {Duration, Time, time} from '../base/time';
import {exists} from '../base/utils';
import {Actions} from '../common/actions';
import {
  defaultViewingOption,
  expandCallsites,
  findRootSize,
  mergeCallsites,
} from '../common/flamegraph_util';
import {
  CallsiteInfo,
  FlamegraphState,
  FlamegraphStateViewingOption,
  ProfileType,
  isHeapGraphDominatorTreeViewingOption,
} from '../common/state';
import {FlamegraphDetails, globals} from '../frontend/globals';
import {publishFlamegraphDetails} from '../frontend/publish';
import {Engine} from '../trace_processor/engine';
import {NUM, STR} from '../trace_processor/query_result';
import {PERF_SAMPLES_PROFILE_TRACK_KIND} from '../tracks/perf_samples_profile';

import {AreaSelectionHandler} from './area_selection_handler';
import {Controller} from './controller';

export function profileType(s: string): ProfileType {
  if (isProfileType(s)) {
    return s;
  }
  if (s.startsWith('heap_profile')) {
    return ProfileType.HEAP_PROFILE;
  }
  throw new Error('Unknown type ${s}');
}

function isProfileType(s: string): s is ProfileType {
  return Object.values(ProfileType).includes(s as ProfileType);
}

function getFlamegraphType(type: ProfileType) {
  switch (type) {
    case ProfileType.HEAP_PROFILE:
    case ProfileType.MIXED_HEAP_PROFILE:
    case ProfileType.NATIVE_HEAP_PROFILE:
    case ProfileType.JAVA_HEAP_SAMPLES:
      return 'native';
    case ProfileType.JAVA_HEAP_GRAPH:
      return 'graph';
    case ProfileType.PERF_SAMPLE:
      return 'perf';
    default:
      const exhaustiveCheck: never = type;
      throw new Error(`Unhandled case: ${exhaustiveCheck}`);
  }
}

export interface FlamegraphControllerArgs {
  engine: Engine;
}
const MIN_PIXEL_DISPLAYED = 1;

class TablesCache {
  private engine: Engine;
  private cache: Map<string, string>;
  private prefix: string;
  private tableId: number;
  private cacheSizeLimit: number;

  constructor(engine: Engine, prefix: string) {
    this.engine = engine;
    this.cache = new Map<string, string>();
    this.prefix = prefix;
    this.tableId = 0;
    this.cacheSizeLimit = 10;
  }

  async getTableName(query: string): Promise<string> {
    let tableName = this.cache.get(query);
    if (tableName === undefined) {
      // TODO(hjd): This should be LRU.
      if (this.cache.size > this.cacheSizeLimit) {
        for (const name of this.cache.values()) {
          await this.engine.query(`drop table ${name}`);
        }
        this.cache.clear();
      }
      tableName = `${this.prefix}_${this.tableId++}`;
      await this.engine.query(
        `create temp table if not exists ${tableName} as ${query}`,
      );
      this.cache.set(query, tableName);
    }
    return tableName;
  }
}

export class FlamegraphController extends Controller<'main'> {
  private flamegraphDatasets: Map<string, CallsiteInfo[]> = new Map();
  private lastSelectedFlamegraphState?: FlamegraphState;
  private requestingData = false;
  private queuedRequest = false;
  private flamegraphDetails: FlamegraphDetails = {};
  private areaSelectionHandler: AreaSelectionHandler;
  private cache: TablesCache;
  private heapGraphSelected: {upid: number; timestamp: time} = {
    upid: -1,
    timestamp: Time.INVALID,
  };

  constructor(private args: FlamegraphControllerArgs) {
    super('main');
    this.cache = new TablesCache(args.engine, 'grouped_callsites');
    this.areaSelectionHandler = new AreaSelectionHandler();
  }

  run() {
    const [hasAreaChanged, area] = this.areaSelectionHandler.getAreaChange();
    if (hasAreaChanged) {
      const upids = [];
      if (!area) {
        this.checkCompletionAndPublishFlamegraph({
          ...globals.flamegraphDetails,
          isInAreaSelection: false,
        });
        return;
      }
      for (const trackId of area.tracks) {
        const track = globals.state.tracks[trackId];
        if (track?.uri) {
          const trackInfo = globals.trackManager.resolveTrackInfo(track.uri);
          if (trackInfo?.kind === PERF_SAMPLES_PROFILE_TRACK_KIND) {
            exists(trackInfo.upid) && upids.push(trackInfo.upid);
          }
        }
      }
      if (upids.length === 0) {
        this.checkCompletionAndPublishFlamegraph({
          ...globals.flamegraphDetails,
          isInAreaSelection: false,
        });
        return;
      }
      globals.dispatch(
        Actions.openFlamegraph({
          upids,
          start: area.start,
          end: area.end,
          type: ProfileType.PERF_SAMPLE,
          viewingOption: defaultViewingOption(ProfileType.PERF_SAMPLE),
        }),
      );
    }
    const selection = globals.state.currentFlamegraphState;
    if (!selection || !this.shouldRequestData(selection)) {
      return;
    }
    if (this.requestingData) {
      this.queuedRequest = true;
      return;
    }
    this.requestingData = true;

    this.assembleFlamegraphDetails(selection, area !== undefined);
  }

  private async assembleFlamegraphDetails(
    selection: FlamegraphState,
    isInAreaSelection: boolean,
  ) {
    const selectedFlamegraphState = {...selection};
    const flamegraphMetadata = await this.getFlamegraphMetadata(
      selection.type,
      selectedFlamegraphState.start,
      selectedFlamegraphState.end,
      selectedFlamegraphState.upids,
    );
    if (flamegraphMetadata !== undefined) {
      Object.assign(this.flamegraphDetails, flamegraphMetadata);
    }

    // TODO(hjd): Clean this up.
    if (
      this.lastSelectedFlamegraphState &&
      this.lastSelectedFlamegraphState.focusRegex !== selection.focusRegex
    ) {
      this.flamegraphDatasets.clear();
    }

    this.lastSelectedFlamegraphState = {...selection};

    const expandedCallsite =
      selectedFlamegraphState.expandedCallsiteByViewingOption[
        selectedFlamegraphState.viewingOption
      ];
    const expandedId = expandedCallsite ? expandedCallsite.id : -1;
    const rootSize = expandedCallsite?.totalSize;

    const key = `${selectedFlamegraphState.upids};${selectedFlamegraphState.start};${selectedFlamegraphState.end}`;

    try {
      const flamegraphData = await this.getFlamegraphData(
        key,
        /* eslint-disable @typescript-eslint/strict-boolean-expressions */
        selectedFlamegraphState.viewingOption
          ? /* eslint-enable */
            selectedFlamegraphState.viewingOption
          : defaultViewingOption(selectedFlamegraphState.type),
        selection.start,
        selection.end,
        selectedFlamegraphState.upids,
        selectedFlamegraphState.type,
        selectedFlamegraphState.focusRegex,
      );
      if (
        flamegraphData !== undefined &&
        // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
        selection &&
        selection.kind === selectedFlamegraphState.kind &&
        selection.start === selectedFlamegraphState.start &&
        selection.end === selectedFlamegraphState.end
      ) {
        const expandedFlamegraphData = expandCallsites(
          flamegraphData,
          expandedId,
        );
        this.prepareAndMergeCallsites(
          expandedFlamegraphData,
          this.lastSelectedFlamegraphState.viewingOption,
          isInAreaSelection,
          rootSize,
          expandedCallsite,
        );
      }
    } finally {
      this.requestingData = false;
      if (this.queuedRequest) {
        this.queuedRequest = false;
        this.run();
      }
    }
  }

  private shouldRequestData(selection: FlamegraphState) {
    return (
      selection.kind === 'FLAMEGRAPH_STATE' &&
      (this.lastSelectedFlamegraphState === undefined ||
        this.lastSelectedFlamegraphState.start !== selection.start ||
        this.lastSelectedFlamegraphState.end !== selection.end ||
        this.lastSelectedFlamegraphState.type !== selection.type ||
        !FlamegraphController.areArraysEqual(
          this.lastSelectedFlamegraphState.upids,
          selection.upids,
        ) ||
        this.lastSelectedFlamegraphState.viewingOption !==
          selection.viewingOption ||
        this.lastSelectedFlamegraphState.focusRegex !== selection.focusRegex ||
        this.lastSelectedFlamegraphState.expandedCallsiteByViewingOption[
          selection.viewingOption
        ] !==
          selection.expandedCallsiteByViewingOption[selection.viewingOption])
    );
  }

  private prepareAndMergeCallsites(
    flamegraphData: CallsiteInfo[],
    viewingOption: FlamegraphStateViewingOption,
    isInAreaSelection: boolean,
    rootSize?: number,
    expandedCallsite?: CallsiteInfo,
  ) {
    this.flamegraphDetails.flamegraph = mergeCallsites(
      flamegraphData,
      this.getMinSizeDisplayed(flamegraphData, rootSize),
    );
    this.flamegraphDetails.expandedCallsite = expandedCallsite;
    this.flamegraphDetails.viewingOption = viewingOption;
    this.flamegraphDetails.isInAreaSelection = isInAreaSelection;
    this.checkCompletionAndPublishFlamegraph(this.flamegraphDetails);
  }

  private async checkCompletionAndPublishFlamegraph(
    flamegraphDetails: FlamegraphDetails,
  ) {
    flamegraphDetails.graphIncomplete =
      (
        await this.args.engine.query(`select value from stats
       where severity = 'error' and name = 'heap_graph_non_finalized_graph'`)
      ).firstRow({value: NUM}).value > 0;
    flamegraphDetails.graphLoading = false;
    publishFlamegraphDetails(flamegraphDetails);
  }

  async getFlamegraphData(
    baseKey: string,
    viewingOption: FlamegraphStateViewingOption,
    start: time,
    end: time,
    upids: number[],
    type: ProfileType,
    focusRegex: string,
  ): Promise<CallsiteInfo[]> {
    let currentData: CallsiteInfo[];
    const key = `${baseKey}-${viewingOption}`;
    if (this.flamegraphDatasets.has(key)) {
      currentData = this.flamegraphDatasets.get(key)!;
    } else {
      publishFlamegraphDetails({
        ...globals.flamegraphDetails,
        graphLoading: true,
      });
      // Collecting data for drawing flamegraph for selected profile.
      // Data needs to be in following format:
      // id, name, parent_id, depth, total_size
      const tableName = await this.prepareViewsAndTables(
        start,
        end,
        upids,
        type,
        focusRegex,
        viewingOption,
      );
      currentData = await this.getFlamegraphDataFromTables(
        tableName,
        viewingOption,
        focusRegex,
      );
      this.flamegraphDatasets.set(key, currentData);
    }
    return currentData;
  }

  async getFlamegraphDataFromTables(
    tableName: string,
    viewingOption: FlamegraphStateViewingOption,
    focusRegex: string,
  ) {
    let orderBy = '';
    let totalColumnName:
      | 'cumulativeSize'
      | 'cumulativeAllocSize'
      | 'cumulativeCount'
      | 'cumulativeAllocCount' = 'cumulativeSize';
    let selfColumnName: 'size' | 'count' = 'size';
    // TODO(fmayer): Improve performance so this is no longer necessary.
    // Alternatively consider collapsing frames of the same label.
    const maxDepth = 100;
    switch (viewingOption) {
      case FlamegraphStateViewingOption.ALLOC_SPACE_MEMORY_ALLOCATED_KEY:
        orderBy = `where cumulative_alloc_size > 0 and depth < ${maxDepth} order by depth, parent_id,
            cumulative_alloc_size desc, name`;
        totalColumnName = 'cumulativeAllocSize';
        selfColumnName = 'size';
        break;
      case FlamegraphStateViewingOption.OBJECTS_ALLOCATED_NOT_FREED_KEY:
        orderBy = `where cumulative_count > 0 and depth < ${maxDepth} order by depth, parent_id,
            cumulative_count desc, name`;
        totalColumnName = 'cumulativeCount';
        selfColumnName = 'count';
        break;
      case FlamegraphStateViewingOption.OBJECTS_ALLOCATED_KEY:
        orderBy = `where cumulative_alloc_count > 0 and depth < ${maxDepth} order by depth, parent_id,
            cumulative_alloc_count desc, name`;
        totalColumnName = 'cumulativeAllocCount';
        selfColumnName = 'count';
        break;
      case FlamegraphStateViewingOption.PERF_SAMPLES_KEY:
      case FlamegraphStateViewingOption.SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY:
        orderBy = `where cumulative_size > 0 and depth < ${maxDepth} order by depth, parent_id,
            cumulative_size desc, name`;
        totalColumnName = 'cumulativeSize';
        selfColumnName = 'size';
        break;
      case FlamegraphStateViewingOption.DOMINATOR_TREE_OBJ_COUNT_KEY:
        orderBy = `where depth < ${maxDepth} order by depth,
          cumulativeCount desc, name`;
        totalColumnName = 'cumulativeCount';
        selfColumnName = 'count';
        break;
      case FlamegraphStateViewingOption.DOMINATOR_TREE_OBJ_SIZE_KEY:
        orderBy = `where depth < ${maxDepth} order by depth,
          cumulativeSize desc, name`;
        totalColumnName = 'cumulativeSize';
        selfColumnName = 'size';
        break;
      default:
        const exhaustiveCheck: never = viewingOption;
        throw new Error(`Unhandled case: ${exhaustiveCheck}`);
        break;
    }

    const callsites = await this.args.engine.query(`
      SELECT
      id as hash,
      IFNULL(IFNULL(DEMANGLE(name), name), '[NULL]') as name,
      IFNULL(parent_id, -1) as parentHash,
      depth,
      cumulative_size as cumulativeSize,
      cumulative_alloc_size as cumulativeAllocSize,
      cumulative_count as cumulativeCount,
      cumulative_alloc_count as cumulativeAllocCount,
      map_name as mapping,
      size,
      count,
      IFNULL(source_file, '') as sourceFile,
      IFNULL(line_number, -1) as lineNumber
      from ${tableName} ${orderBy}`);

    const flamegraphData: CallsiteInfo[] = [];
    const hashToindex: Map<number, number> = new Map();
    const it = callsites.iter({
      hash: NUM,
      name: STR,
      parentHash: NUM,
      depth: NUM,
      cumulativeSize: NUM,
      cumulativeAllocSize: NUM,
      cumulativeCount: NUM,
      cumulativeAllocCount: NUM,
      mapping: STR,
      sourceFile: STR,
      lineNumber: NUM,
      size: NUM,
      count: NUM,
    });
    for (let i = 0; it.valid(); ++i, it.next()) {
      const hash = it.hash;
      let name = it.name;
      const parentHash = it.parentHash;
      const depth = it.depth;
      const totalSize = it[totalColumnName];
      const selfSize = it[selfColumnName];
      const mapping = it.mapping;
      const highlighted =
        focusRegex !== '' &&
        name.toLocaleLowerCase().includes(focusRegex.toLocaleLowerCase());
      const parentId = hashToindex.has(+parentHash)
        ? hashToindex.get(+parentHash)!
        : -1;

      let location: string | undefined;
      if (/[a-zA-Z]/i.test(it.sourceFile)) {
        location = it.sourceFile;
        if (it.lineNumber !== -1) {
          location += `:${it.lineNumber}`;
        }
      }

      if (depth === maxDepth - 1) {
        name += ' [tree truncated]';
      }
      // Instead of hash, we will store index of callsite in this original array
      // as an id of callsite. That way, we have quicker access to parent and it
      // will stay unique:
      hashToindex.set(hash, i);

      flamegraphData.push({
        id: i,
        totalSize,
        depth,
        parentId,
        name,
        selfSize,
        mapping,
        merged: false,
        highlighted,
        location,
      });
    }
    return flamegraphData;
  }

  private async prepareViewsAndTables(
    start: time,
    end: time,
    upids: number[],
    type: ProfileType,
    focusRegex: string,
    viewingOption: FlamegraphStateViewingOption,
  ): Promise<string> {
    const flamegraphType = getFlamegraphType(type);
    if (type === ProfileType.PERF_SAMPLE) {
      let upid: string;
      let upidGroup: string;
      if (upids.length > 1) {
        upid = `NULL`;
        upidGroup = `'${FlamegraphController.serializeUpidGroup(upids)}'`;
      } else {
        upid = `${upids[0]}`;
        upidGroup = `NULL`;
      }
      return this.cache.getTableName(
        `select id, name, map_name, parent_id, depth, cumulative_size,
          cumulative_alloc_size, cumulative_count, cumulative_alloc_count,
          size, alloc_size, count, alloc_count, source_file, line_number
          from experimental_flamegraph(
            '${flamegraphType}',
            NULL,
            '>=${start},<=${end}',
            ${upid},
            ${upidGroup},
            '${focusRegex}'
          )`,
      );
    }
    if (
      type === ProfileType.JAVA_HEAP_GRAPH &&
      isHeapGraphDominatorTreeViewingOption(viewingOption)
    ) {
      return this.cache.getTableName(
        await this.loadHeapGraphDominatorTreeQuery(upids[0], end),
      );
    }
    return this.cache.getTableName(
      `select id, name, map_name, parent_id, depth, cumulative_size,
          cumulative_alloc_size, cumulative_count, cumulative_alloc_count,
          size, alloc_size, count, alloc_count, source_file, line_number
          from experimental_flamegraph(
            '${flamegraphType}',
            ${end},
            NULL,
            ${upids[0]},
            NULL,
            '${focusRegex}'
          )`,
    );
  }

  private async loadHeapGraphDominatorTreeQuery(upid: number, timestamp: time) {
    const selectTreeQuery = `
    -- cache invalidate: upid ${upid}, ts ${timestamp}
    SELECT * FROM heap_graph_type_dominated`;
    if (
      this.heapGraphSelected.upid === upid &&
      this.heapGraphSelected.timestamp === timestamp
    ) {
      return selectTreeQuery;
    }
    this.heapGraphSelected = {upid, timestamp};
    this.args.engine.query(`
    INCLUDE PERFETTO MODULE memory.heap_graph_dominator_tree;

    -- heap graph dominator tree with objects as nodes and all relavant
    -- object self stats and dominated stats
    CREATE PERFETTO TABLE heap_graph_object_dominated AS
    SELECT
     node.id,
     node.idom_id,
     node.dominated_obj_count,
     node.dominated_size_bytes + node.dominated_native_size_bytes AS dominated_size,
     node.depth,
     obj.type_id,
     obj.root_type,
     obj.self_size + obj.native_size AS self_size
    FROM memory_heap_graph_dominator_tree node
    JOIN heap_graph_object obj USING(id)
    WHERE obj.upid = ${upid} AND obj.graph_sample_ts = ${timestamp}
    -- required to accelerate the recursive cte below
    ORDER BY idom_id;

    -- calculate for each object node in the dominator tree the
    -- HASH(path of type_id's from the super root to the object)
    CREATE PERFETTO TABLE _dominator_tree_path_hash AS
    WITH RECURSIVE _tree_visitor(id, path, path_hash) AS (
      SELECT
        id,
        CAST(type_id AS text) || '-' || IFNULL(root_type, '') AS path,
        HASH(
          CAST(type_id AS text) || '-' || IFNULL(root_type, '')
        ) AS path_hash
      FROM heap_graph_object_dominated
      WHERE depth = 1
      UNION ALL
      SELECT
        child.id,
        parent.path || '/' || CAST(type_id AS text) AS path,
        HASH(parent.path || '/' || CAST(type_id AS text)) AS path_hash
      FROM heap_graph_object_dominated child
      JOIN _tree_visitor parent ON child.idom_id = parent.id
    )
    SELECT * from _tree_visitor
    ORDER BY id;

    -- merge object nodes with the same path into one "class type node", so the
    -- end result is a tree where nodes are identified by their types and the
    -- dominator relationships are preserved.
    CREATE PERFETTO TABLE heap_graph_type_dominated AS
    SELECT
      map.path_hash as id,
      COALESCE(cls.deobfuscated_name, cls.name, '[NULL]') || IIF(
        node.root_type IS NOT NULL,
        ' [' || node.root_type || ']', ''
      ) AS name,
      IFNULL(parent_map.path_hash, -1) AS parent_id,
      node.depth - 1 AS depth,
      sum(dominated_size) AS cumulative_size,
      -1 AS cumulative_alloc_size,
      sum(dominated_obj_count) AS cumulative_count,
      -1 AS cumulative_alloc_count,
      '' as map_name,
      '' as source_file,
      -1 as line_number,
      sum(self_size) AS size,
      count(*) AS count
    FROM heap_graph_object_dominated node
    JOIN _dominator_tree_path_hash map USING(id)
    LEFT JOIN _dominator_tree_path_hash parent_map ON node.idom_id = parent_map.id
    JOIN heap_graph_class cls ON node.type_id = cls.id
    GROUP BY map.path_hash, name, parent_id, depth, map_name, source_file, line_number;`);

    return selectTreeQuery;
  }

  getMinSizeDisplayed(
    flamegraphData: CallsiteInfo[],
    rootSize?: number,
  ): number {
    const timeState = globals.state.frontendLocalState.visibleState;
    const dur = globals.stateVisibleTime().duration;
    // TODO(stevegolton): Does this actually do what we want???
    let width = Duration.toSeconds(dur / timeState.resolution);
    // TODO(168048193): Remove screen size hack:
    width = Math.max(width, 800);
    if (rootSize === undefined) {
      rootSize = findRootSize(flamegraphData);
    }
    return (MIN_PIXEL_DISPLAYED * rootSize) / width;
  }

  async getFlamegraphMetadata(
    type: ProfileType,
    start: time,
    end: time,
    upids: number[],
  ): Promise<FlamegraphDetails | undefined> {
    // Don't do anything if selection of the marker stayed the same.
    if (
      this.lastSelectedFlamegraphState !== undefined &&
      this.lastSelectedFlamegraphState.start === start &&
      this.lastSelectedFlamegraphState.end === end &&
      FlamegraphController.areArraysEqual(
        this.lastSelectedFlamegraphState.upids,
        upids,
      )
    ) {
      return undefined;
    }

    // Collecting data for more information about profile, such as:
    // total memory allocated, memory that is allocated and not freed.
    const upidGroup = FlamegraphController.serializeUpidGroup(upids);

    const result = await this.args.engine.query(
      `select pid from process where upid in (${upidGroup})`,
    );
    const it = result.iter({pid: NUM});
    const pids = [];
    for (let i = 0; it.valid(); ++i, it.next()) {
      pids.push(it.pid);
    }
    return {start, dur: end - start, pids, upids, type};
  }

  private static areArraysEqual(a: number[], b: number[]) {
    if (a.length !== b.length) {
      return false;
    }
    for (let i = 0; i < a.length; i++) {
      if (a[i] !== b[i]) {
        return false;
      }
    }
    return true;
  }

  private static serializeUpidGroup(upids: number[]) {
    return new Array(upids).join();
  }
}
