// 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 {searchSegment} from '../base/binary_search';
import {cropText} from '../common/canvas_utils';

import {CallsiteInfo} from '../common/state';

interface Node {
  width: number;
  x: number;
  nextXForChildren: number;
  size: number;
}

interface CallsiteInfoWidth {
  callsite: CallsiteInfo;
  width: number;
}

// Height of one 'row' on the flame chart including 1px of whitespace
// below the box.
const NODE_HEIGHT = 18;

export const FLAMEGRAPH_HOVERED_COLOR = 'hsl(224, 45%, 55%)';

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

export interface NodeRendering {
  totalSize?: string;
  selfSize?: string;
}

export class Flamegraph {
  private nodeRendering: NodeRendering = {};
  private flamegraphData: CallsiteInfo[];
  private highlightSomeNodes = false;
  private maxDepth = -1;
  private totalSize = -1;
  // Initialised on first draw() call
  private labelCharWidth = 0;
  private labelFontStyle = '12px Roboto Mono';
  private rolloverFontStyle = '12px Roboto Condensed';
  // Key for the map is depth followed by x coordinate - `depth;x`
  private graphData: Map<string, CallsiteInfoWidth> = new Map();
  private xStartsPerDepth: Map<number, number[]> = new Map();

  private hoveredX = -1;
  private hoveredY = -1;
  private hoveredCallsite?: CallsiteInfo;
  private clickedCallsite?: CallsiteInfo;

  private startingY = 0;

  constructor(flamegraphData: CallsiteInfo[]) {
    this.flamegraphData = flamegraphData;
    this.findMaxDepth();
  }

  private findMaxDepth() {
    this.maxDepth =
        Math.max(...this.flamegraphData.map((value) => value.depth));
  }

  // Instead of highlighting the interesting nodes, we actually want to
  // de-emphasize the non-highlighted nodes. Returns true if there
  // are any highlighted nodes in the flamegraph.
  private highlightingExists() {
    this.highlightSomeNodes = this.flamegraphData.some((e) => e.highlighted);
  }

  generateColor(name: string, isGreyedOut = false, highlighted: boolean):
      string {
    if (isGreyedOut) {
      return '#d9d9d9';
    }
    if (name === 'unknown' || name === 'root') {
      return '#c0c0c0';
    }
    let x = 0;
    for (let i = 0; i < name.length; i += 1) {
      x += name.charCodeAt(i) % 64;
    }
    x = x % 360;
    let l = '76';
    // Make non-highlighted node lighter.
    if (this.highlightSomeNodes && !highlighted) {
      l = '90';
    }
    return `hsl(${x}deg, 45%, ${l}%)`;
  }

  // Caller will have to call draw method after updating data to have updated
  // graph.
  updateDataIfChanged(
      nodeRendering: NodeRendering, flamegraphData: CallsiteInfo[],
      clickedCallsite?: CallsiteInfo) {
    this.nodeRendering = nodeRendering;
    this.clickedCallsite = clickedCallsite;
    if (this.flamegraphData === flamegraphData) {
      return;
    }
    this.flamegraphData = flamegraphData;
    this.clickedCallsite = clickedCallsite;
    this.findMaxDepth();
    this.highlightingExists();
    // Finding total size of roots.
    this.totalSize = findRootSize(flamegraphData);
  }

  draw(
      ctx: CanvasRenderingContext2D, width: number, height: number, x = 0,
      y = 0, unit = 'B') {
    if (this.flamegraphData === undefined) {
      return;
    }

    ctx.font = this.labelFontStyle;
    ctx.textBaseline = 'middle';
    if (this.labelCharWidth === 0) {
      this.labelCharWidth = ctx.measureText('_').width;
    }

    this.startingY = y;

    // For each node, we use this map to get information about it's parent
    // (total size of it, width and where it starts in graph) so we can
    // calculate it's own position in graph.
    const nodesMap = new Map<number, Node>();
    let currentY = y;
    nodesMap.set(-1, {width, nextXForChildren: x, size: this.totalSize, x});

    // Initialize data needed for click/hover behavior.
    this.graphData = new Map();
    this.xStartsPerDepth = new Map();

    // Draw root node.
    ctx.fillStyle = this.generateColor('root', false, false);
    ctx.fillRect(x, currentY, width, NODE_HEIGHT - 1);
    const text = cropText(
        `root: ${
            this.displaySize(
                this.totalSize, unit, unit === 'B' ? 1024 : 1000)}`,
        this.labelCharWidth,
        width - 2);
    ctx.fillStyle = 'black';
    ctx.fillText(text, x + 5, currentY + (NODE_HEIGHT - 1) / 2);
    currentY += NODE_HEIGHT;

    // Set style for borders.
    ctx.strokeStyle = 'white';
    ctx.lineWidth = 0.5;

    for (let i = 0; i < this.flamegraphData.length; i++) {
      if (currentY > height) {
        break;
      }
      const value = this.flamegraphData[i];
      const parentNode = nodesMap.get(value.parentId);
      if (parentNode === undefined) {
        continue;
      }

      const isClicked = this.clickedCallsite !== undefined;
      const isFullWidth =
          isClicked && value.depth <= this.clickedCallsite!.depth;
      const isGreyedOut =
          isClicked && value.depth < this.clickedCallsite!.depth;

      const parent = value.parentId;
      const parentSize = parent === -1 ? this.totalSize : parentNode.size;
      // Calculate node's width based on its proportion in parent.
      const width =
          (isFullWidth ? 1 : value.totalSize / parentSize) * parentNode.width;

      const currentX = parentNode.nextXForChildren;
      currentY = y + NODE_HEIGHT * (value.depth + 1);

      // Draw node.
      const name = this.getCallsiteName(value);
      ctx.fillStyle = this.generateColor(name, isGreyedOut, value.highlighted);
      ctx.fillRect(currentX, currentY, width, NODE_HEIGHT - 1);

      // Set current node's data in map for children to use.
      nodesMap.set(value.id, {
        width,
        nextXForChildren: currentX,
        size: value.totalSize,
        x: currentX,
      });
      // Update next x coordinate in parent.
      nodesMap.set(value.parentId, {
        width: parentNode.width,
        nextXForChildren: currentX + width,
        size: parentNode.size,
        x: parentNode.x,
      });

      // Draw name.
      const labelPaddingPx = 5;
      const maxLabelWidth = width - labelPaddingPx * 2;
      let text = cropText(name, this.labelCharWidth, maxLabelWidth);
      // If cropped text and the original text are within 20% we keep the
      // original text and just squish it a bit.
      if (text.length * 1.2 > name.length) {
        text = name;
      }
      ctx.fillStyle = 'black';
      ctx.fillText(
          text,
          currentX + labelPaddingPx,
          currentY + (NODE_HEIGHT - 1) / 2,
          maxLabelWidth);

      // Draw border on the right of node.
      ctx.beginPath();
      ctx.moveTo(currentX + width, currentY);
      ctx.lineTo(currentX + width, currentY + NODE_HEIGHT);
      ctx.stroke();

      // Add this node for recognizing in click/hover.
      // Map graphData contains one callsite which is on that depth and X
      // start. Map xStartsPerDepth for each depth contains all X start
      // coordinates that callsites on that level have.
      this.graphData.set(
          `${value.depth};${currentX}`, {callsite: value, width});
      const xStarts = this.xStartsPerDepth.get(value.depth);
      if (xStarts === undefined) {
        this.xStartsPerDepth.set(value.depth, [currentX]);
      } else {
        xStarts.push(currentX);
      }
    }

    // Draw the tooltip.
    if (this.hoveredX > -1 && this.hoveredY > -1 && this.hoveredCallsite) {
      // Must set these before measureText below.
      ctx.font = this.rolloverFontStyle;
      ctx.textBaseline = 'top';

      // Size in px of the border around the text and the edge of the rollover
      // background.
      const paddingPx = 8;
      // Size in px of the x and y offset between the mouse and the top left
      // corner of the rollover box.
      const offsetPx = 4;

      const lines: string[] = [];

      let textWidth = this.addToTooltip(
          this.getCallsiteName(this.hoveredCallsite),
          width - paddingPx,
          ctx,
          lines);
      if (this.hoveredCallsite.location != null) {
        textWidth = Math.max(
            textWidth,
            this.addToTooltip(
                this.hoveredCallsite.location, width, ctx, lines));
      }
      textWidth = Math.max(
          textWidth,
          this.addToTooltip(this.hoveredCallsite.mapping, width, ctx, lines));

      if (this.nodeRendering.totalSize !== undefined) {
        const percentage =
            this.hoveredCallsite.totalSize / this.totalSize * 100;
        const totalSizeText = `${this.nodeRendering.totalSize}: ${
            this.displaySize(
                this.hoveredCallsite.totalSize,
                unit,
                unit === 'B' ? 1024 : 1000)} (${percentage.toFixed(2)}%)`;
        textWidth = Math.max(
            textWidth, this.addToTooltip(totalSizeText, width, ctx, lines));
      }

      if (this.nodeRendering.selfSize !== undefined &&
          this.hoveredCallsite.selfSize > 0) {
        const selfPercentage =
            this.hoveredCallsite.selfSize / this.totalSize * 100;
        const selfSizeText = `${this.nodeRendering.selfSize}: ${
            this.displaySize(
                this.hoveredCallsite.selfSize,
                unit,
                unit === 'B' ? 1024 : 1000)} (${selfPercentage.toFixed(2)}%)`;
        textWidth = Math.max(
            textWidth, this.addToTooltip(selfSizeText, width, ctx, lines));
      }

      // Compute a line height as the bounding box height + 50%:
      const heightSample = ctx.measureText(
          'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
      const lineHeight =
          Math.round(heightSample.actualBoundingBoxDescent * 1.5);

      const rectWidth = textWidth + 2 * paddingPx;
      const rectHeight = lineHeight * lines.length + 2 * paddingPx;

      let rectXStart = this.hoveredX + offsetPx;
      let rectYStart = this.hoveredY + offsetPx;

      if (rectXStart + rectWidth > width) {
        rectXStart = width - rectWidth;
      }

      if (rectYStart + rectHeight > height) {
        rectYStart = height - rectHeight;
      }

      ctx.fillStyle = 'rgba(255, 255, 255, 0.9)';
      ctx.fillRect(rectXStart, rectYStart, rectWidth, rectHeight);
      ctx.fillStyle = 'hsl(200, 50%, 40%)';
      ctx.textAlign = 'left';
      for (let i = 0; i < lines.length; i++) {
        const line = lines[i];
        ctx.fillText(
            line,
            rectXStart + paddingPx,
            rectYStart + paddingPx + i * lineHeight);
      }
    }
  }

  private addToTooltip(
      text: string, width: number, ctx: CanvasRenderingContext2D,
      lines: string[]): number {
    const lineSplitter: LineSplitter =
        splitIfTooBig(text, width, ctx.measureText(text).width);
    lines.push(...lineSplitter.lines);
    return lineSplitter.lineWidth;
  }

  private getCallsiteName(value: CallsiteInfo): string {
    return value.name === undefined || value.name === '' ? 'unknown' :
                                                           value.name;
  }

  private displaySize(totalSize: number, unit: string, step = 1024): string {
    if (unit === '') return totalSize.toLocaleString();
    if (totalSize === 0) return `0 ${unit}`;
    const units = [
      ['', 1],
      ['K', step],
      ['M', Math.pow(step, 2)],
      ['G', Math.pow(step, 3)],
    ];
    let unitsIndex = Math.trunc(Math.log(totalSize) / Math.log(step));
    unitsIndex = unitsIndex > units.length - 1 ? units.length - 1 : unitsIndex;
    const result = totalSize / +units[unitsIndex][1];
    const resultString = totalSize % +units[unitsIndex][1] === 0 ?
        result.toString() :
        result.toFixed(2);
    return `${resultString} ${units[unitsIndex][0]}${unit}`;
  }

  onMouseMove({x, y}: {x: number, y: number}) {
    this.hoveredX = x;
    this.hoveredY = y;
    this.hoveredCallsite = this.findSelectedCallsite(x, y);
    const isCallsiteSelected = this.hoveredCallsite !== undefined;
    if (!isCallsiteSelected) {
      this.onMouseOut();
    }
    return isCallsiteSelected;
  }

  onMouseOut() {
    this.hoveredX = -1;
    this.hoveredY = -1;
    this.hoveredCallsite = undefined;
  }

  onMouseClick({x, y}: {x: number, y: number}): CallsiteInfo|undefined {
    const clickedCallsite = this.findSelectedCallsite(x, y);
    // TODO(b/148596659): Allow to expand [merged] callsites. Currently,
    // this expands to the biggest of the nodes that were merged, which
    // is confusing, so we disallow clicking on them.
    if (clickedCallsite === undefined || clickedCallsite.merged) {
      return undefined;
    }
    return clickedCallsite;
  }

  private findSelectedCallsite(x: number, y: number): CallsiteInfo|undefined {
    const depth =
        Math.trunc((y - this.startingY) / NODE_HEIGHT) - 1;  // at 0 is root
    if (depth >= 0 && this.xStartsPerDepth.has(depth)) {
      const startX = this.searchSmallest(this.xStartsPerDepth.get(depth)!, x);
      const result = this.graphData.get(`${depth};${startX}`);
      if (result !== undefined) {
        const width = result.width;
        return startX + width >= x ? result.callsite : undefined;
      }
    }
    return undefined;
  }

  searchSmallest(haystack: number[], needle: number): number {
    haystack = haystack.sort((n1, n2) => n1 - n2);
    const [left] = searchSegment(haystack, needle);
    return left === -1 ? -1 : haystack[left];
  }

  getHeight(): number {
    return this.flamegraphData.length === 0 ? 0 :
                                              (this.maxDepth + 2) * NODE_HEIGHT;
  }
}

export interface LineSplitter {
  lineWidth: number;
  lines: string[];
}

export function splitIfTooBig(
    line: string, width: number, lineWidth: number): LineSplitter {
  if (line === '') return {lineWidth, lines: []};
  const lines: string[] = [];
  const charWidth = lineWidth / line.length;
  const maxWidth = width - 32;
  const maxLineLen = Math.trunc(maxWidth / charWidth);
  while (line.length > 0) {
    lines.push(line.slice(0, maxLineLen));
    line = line.slice(maxLineLen);
  }
  lineWidth = Math.min(maxLineLen * charWidth, lineWidth);
  return {lineWidth, lines};
}
