// 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 {featureFlags} from '../core/feature_flags';
import {CallsiteInfo, FlamegraphStateViewingOption, ProfileType} from './state';

interface ViewingOption {
  option: FlamegraphStateViewingOption;
  name: string;
}

const SHOW_HEAP_GRAPH_DOMINATOR_TREE_FLAG = featureFlags.register({
  id: 'showHeapGraphDominatorTree',
  name: 'Show heap graph dominator tree',
  description: 'Show dominated size and objects tabs in Java heap graph view.',
  defaultValue: false,
});

export function viewingOptions(profileType: ProfileType): Array<ViewingOption> {
  switch (profileType) {
    case ProfileType.PERF_SAMPLE:
      return [
        {
          option: FlamegraphStateViewingOption.PERF_SAMPLES_KEY,
          name: 'Samples',
        },
      ];
    case ProfileType.JAVA_HEAP_GRAPH:
      return [
        {
          option:
            FlamegraphStateViewingOption.SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY,
          name: 'Size',
        },
        {
          option: FlamegraphStateViewingOption.OBJECTS_ALLOCATED_NOT_FREED_KEY,
          name: 'Objects',
        },
      ].concat(
        SHOW_HEAP_GRAPH_DOMINATOR_TREE_FLAG.get()
          ? [
              {
                option:
                  FlamegraphStateViewingOption.DOMINATOR_TREE_OBJ_SIZE_KEY,
                name: 'Dominated size',
              },
              {
                option:
                  FlamegraphStateViewingOption.DOMINATOR_TREE_OBJ_COUNT_KEY,
                name: 'Dominated objects',
              },
            ]
          : [],
      );
    case ProfileType.HEAP_PROFILE:
      return [
        {
          option:
            FlamegraphStateViewingOption.SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY,
          name: 'Unreleased size',
        },
        {
          option: FlamegraphStateViewingOption.OBJECTS_ALLOCATED_NOT_FREED_KEY,
          name: 'Unreleased count',
        },
        {
          option: FlamegraphStateViewingOption.ALLOC_SPACE_MEMORY_ALLOCATED_KEY,
          name: 'Total size',
        },
        {
          option: FlamegraphStateViewingOption.OBJECTS_ALLOCATED_KEY,
          name: 'Total count',
        },
      ];
    case ProfileType.NATIVE_HEAP_PROFILE:
      return [
        {
          option:
            FlamegraphStateViewingOption.SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY,
          name: 'Unreleased malloc size',
        },
        {
          option: FlamegraphStateViewingOption.OBJECTS_ALLOCATED_NOT_FREED_KEY,
          name: 'Unreleased malloc count',
        },
        {
          option: FlamegraphStateViewingOption.ALLOC_SPACE_MEMORY_ALLOCATED_KEY,
          name: 'Total malloc size',
        },
        {
          option: FlamegraphStateViewingOption.OBJECTS_ALLOCATED_KEY,
          name: 'Total malloc count',
        },
      ];
    case ProfileType.JAVA_HEAP_SAMPLES:
      return [
        {
          option: FlamegraphStateViewingOption.ALLOC_SPACE_MEMORY_ALLOCATED_KEY,
          name: 'Total allocation size',
        },
        {
          option: FlamegraphStateViewingOption.OBJECTS_ALLOCATED_KEY,
          name: 'Total allocation count',
        },
      ];
    case ProfileType.MIXED_HEAP_PROFILE:
      return [
        {
          option: FlamegraphStateViewingOption.ALLOC_SPACE_MEMORY_ALLOCATED_KEY,
          name: 'Total allocation size (malloc + java)',
        },
        {
          option: FlamegraphStateViewingOption.OBJECTS_ALLOCATED_KEY,
          name: 'Total allocation count (malloc + java)',
        },
      ];
    default:
      const exhaustiveCheck: never = profileType;
      throw new Error(`Unhandled case: ${exhaustiveCheck}`);
  }
}

export function defaultViewingOption(
  profileType: ProfileType,
): FlamegraphStateViewingOption {
  return viewingOptions(profileType)[0].option;
}

export function expandCallsites(
  data: CallsiteInfo[],
  clickedCallsiteIndex: number,
): CallsiteInfo[] {
  if (clickedCallsiteIndex === -1) return data;
  const expandedCallsites: CallsiteInfo[] = [];
  if (clickedCallsiteIndex >= data.length || clickedCallsiteIndex < -1) {
    return expandedCallsites;
  }
  const clickedCallsite = data[clickedCallsiteIndex];
  expandedCallsites.unshift(clickedCallsite);
  // Adding parents
  let parentId = clickedCallsite.parentId;
  while (parentId > -1) {
    expandedCallsites.unshift(data[parentId]);
    parentId = data[parentId].parentId;
  }
  // Adding children
  const parents: number[] = [];
  parents.push(clickedCallsiteIndex);
  for (let i = clickedCallsiteIndex + 1; i < data.length; i++) {
    const element = data[i];
    if (parents.includes(element.parentId)) {
      expandedCallsites.push(element);
      parents.push(element.id);
    }
  }
  return expandedCallsites;
}

// Merge callsites that have approximately width less than
// MIN_PIXEL_DISPLAYED. All small callsites in the same depth and with same
// parent will be merged to one with total size of all merged callsites.
export function mergeCallsites(data: CallsiteInfo[], minSizeDisplayed: number) {
  const mergedData: CallsiteInfo[] = [];
  const mergedCallsites: Map<number, number> = new Map();
  for (let i = 0; i < data.length; i++) {
    // When a small callsite is found, it will be merged with other small
    // callsites of the same depth. So if the current callsite has already been
    // merged we can skip it.
    if (mergedCallsites.has(data[i].id)) {
      continue;
    }
    const copiedCallsite = copyCallsite(data[i]);
    copiedCallsite.parentId = getCallsitesParentHash(
      copiedCallsite,
      mergedCallsites,
    );

    let mergedAny = false;
    // If current callsite is small, find other small callsites with same depth
    // and parent and merge them into the current one, marking them as merged.
    if (copiedCallsite.totalSize <= minSizeDisplayed && i + 1 < data.length) {
      let j = i + 1;
      let nextCallsite = data[j];
      while (j < data.length && copiedCallsite.depth === nextCallsite.depth) {
        if (
          copiedCallsite.parentId ===
            getCallsitesParentHash(nextCallsite, mergedCallsites) &&
          nextCallsite.totalSize <= minSizeDisplayed
        ) {
          copiedCallsite.totalSize += nextCallsite.totalSize;
          mergedCallsites.set(nextCallsite.id, copiedCallsite.id);
          mergedAny = true;
        }
        j++;
        nextCallsite = data[j];
      }
      if (mergedAny) {
        copiedCallsite.name = '[merged]';
        copiedCallsite.merged = true;
      }
    }
    mergedData.push(copiedCallsite);
  }
  return mergedData;
}

function copyCallsite(callsite: CallsiteInfo): CallsiteInfo {
  return {
    id: callsite.id,
    parentId: callsite.parentId,
    depth: callsite.depth,
    name: callsite.name,
    totalSize: callsite.totalSize,
    mapping: callsite.mapping,
    selfSize: callsite.selfSize,
    merged: callsite.merged,
    highlighted: callsite.highlighted,
    location: callsite.location,
  };
}

function getCallsitesParentHash(
  callsite: CallsiteInfo,
  map: Map<number, number>,
): number {
  return map.has(callsite.parentId)
    ? +map.get(callsite.parentId)!
    : callsite.parentId;
}
export function findRootSize(data: CallsiteInfo[]) {
  let totalSize = 0;
  let i = 0;
  while (i < data.length && data[i].depth === 0) {
    totalSize += data[i].totalSize;
    i++;
  }
  return totalSize;
}
