/*
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @unrestricted
 */
export class AllocationProfile {
  constructor(profile, liveObjectStats) {
    this._strings = profile.strings;
    this._liveObjectStats = liveObjectStats;

    this._nextNodeId = 1;
    this._functionInfos = [];
    this._idToNode = {};
    this._idToTopDownNode = {};
    this._collapsedTopNodeIdToFunctionInfo = {};

    this._traceTops = null;

    this._buildFunctionAllocationInfos(profile);
    this._traceTree = this._buildAllocationTree(profile, liveObjectStats);
  }

  _buildFunctionAllocationInfos(profile) {
    const strings = this._strings;

    const functionInfoFields = profile.snapshot.meta.trace_function_info_fields;
    const functionNameOffset = functionInfoFields.indexOf('name');
    const scriptNameOffset = functionInfoFields.indexOf('script_name');
    const scriptIdOffset = functionInfoFields.indexOf('script_id');
    const lineOffset = functionInfoFields.indexOf('line');
    const columnOffset = functionInfoFields.indexOf('column');
    const functionInfoFieldCount = functionInfoFields.length;

    const rawInfos = profile.trace_function_infos;
    const infoLength = rawInfos.length;
    const functionInfos = this._functionInfos = new Array(infoLength / functionInfoFieldCount);
    let index = 0;
    for (let i = 0; i < infoLength; i += functionInfoFieldCount) {
      functionInfos[index++] = new FunctionAllocationInfo(
          strings[rawInfos[i + functionNameOffset]], strings[rawInfos[i + scriptNameOffset]],
          rawInfos[i + scriptIdOffset], rawInfos[i + lineOffset], rawInfos[i + columnOffset]);
    }
  }

  _buildAllocationTree(profile, liveObjectStats) {
    const traceTreeRaw = profile.trace_tree;
    const functionInfos = this._functionInfos;
    const idToTopDownNode = this._idToTopDownNode;

    const traceNodeFields = profile.snapshot.meta.trace_node_fields;
    const nodeIdOffset = traceNodeFields.indexOf('id');
    const functionInfoIndexOffset = traceNodeFields.indexOf('function_info_index');
    const allocationCountOffset = traceNodeFields.indexOf('count');
    const allocationSizeOffset = traceNodeFields.indexOf('size');
    const childrenOffset = traceNodeFields.indexOf('children');
    const nodeFieldCount = traceNodeFields.length;

    function traverseNode(rawNodeArray, nodeOffset, parent) {
      const functionInfo = functionInfos[rawNodeArray[nodeOffset + functionInfoIndexOffset]];
      const id = rawNodeArray[nodeOffset + nodeIdOffset];
      const stats = liveObjectStats[id];
      const liveCount = stats ? stats.count : 0;
      const liveSize = stats ? stats.size : 0;
      const result = new TopDownAllocationNode(
          id, functionInfo, rawNodeArray[nodeOffset + allocationCountOffset],
          rawNodeArray[nodeOffset + allocationSizeOffset], liveCount, liveSize, parent);
      idToTopDownNode[id] = result;
      functionInfo.addTraceTopNode(result);

      const rawChildren = rawNodeArray[nodeOffset + childrenOffset];
      for (let i = 0; i < rawChildren.length; i += nodeFieldCount) {
        result.children.push(traverseNode(rawChildren, i, result));
      }

      return result;
    }

    return traverseNode(traceTreeRaw, 0, null);
  }

  /**
   * @return {!Array.<!HeapSnapshotModel.SerializedAllocationNode>}
   */
  serializeTraceTops() {
    if (this._traceTops) {
      return this._traceTops;
    }
    const result = this._traceTops = [];
    const functionInfos = this._functionInfos;
    for (let i = 0; i < functionInfos.length; i++) {
      const info = functionInfos[i];
      if (info.totalCount === 0) {
        continue;
      }
      const nodeId = this._nextNodeId++;
      const isRoot = i === 0;
      result.push(this._serializeNode(
          nodeId, info, info.totalCount, info.totalSize, info.totalLiveCount, info.totalLiveSize, !isRoot));
      this._collapsedTopNodeIdToFunctionInfo[nodeId] = info;
    }
    result.sort(function(a, b) {
      return b.size - a.size;
    });
    return result;
  }

  /**
   * @param {number} nodeId
   * @return {!HeapSnapshotModel.AllocationNodeCallers}
   */
  serializeCallers(nodeId) {
    let node = this._ensureBottomUpNode(nodeId);
    const nodesWithSingleCaller = [];
    while (node.callers().length === 1) {
      node = node.callers()[0];
      nodesWithSingleCaller.push(this._serializeCaller(node));
    }

    const branchingCallers = [];
    const callers = node.callers();
    for (let i = 0; i < callers.length; i++) {
      branchingCallers.push(this._serializeCaller(callers[i]));
    }

    return new HeapSnapshotModel.AllocationNodeCallers(nodesWithSingleCaller, branchingCallers);
  }

  /**
   * @param {number} traceNodeId
   * @return {!Array.<!HeapSnapshotModel.AllocationStackFrame>}
   */
  serializeAllocationStack(traceNodeId) {
    let node = this._idToTopDownNode[traceNodeId];
    const result = [];
    while (node) {
      const functionInfo = node.functionInfo;
      result.push(new HeapSnapshotModel.AllocationStackFrame(
          functionInfo.functionName, functionInfo.scriptName, functionInfo.scriptId, functionInfo.line,
          functionInfo.column));
      node = node.parent;
    }
    return result;
  }

  /**
   * @param {number} allocationNodeId
   * @return {!Array.<number>}
   */
  traceIds(allocationNodeId) {
    return this._ensureBottomUpNode(allocationNodeId).traceTopIds;
  }

  /**
   * @param {number} nodeId
   * @return {!BottomUpAllocationNode}
   */
  _ensureBottomUpNode(nodeId) {
    let node = this._idToNode[nodeId];
    if (!node) {
      const functionInfo = this._collapsedTopNodeIdToFunctionInfo[nodeId];
      node = functionInfo.bottomUpRoot();
      delete this._collapsedTopNodeIdToFunctionInfo[nodeId];
      this._idToNode[nodeId] = node;
    }
    return node;
  }

  /**
   * @param {!BottomUpAllocationNode} node
   * @return {!HeapSnapshotModel.SerializedAllocationNode}
   */
  _serializeCaller(node) {
    const callerId = this._nextNodeId++;
    this._idToNode[callerId] = node;
    return this._serializeNode(
        callerId, node.functionInfo, node.allocationCount, node.allocationSize, node.liveCount, node.liveSize,
        node.hasCallers());
  }

  /**
   * @param {number} nodeId
   * @param {!FunctionAllocationInfo} functionInfo
   * @param {number} count
   * @param {number} size
   * @param {number} liveCount
   * @param {number} liveSize
   * @param {boolean} hasChildren
   * @return {!HeapSnapshotModel.SerializedAllocationNode}
   */
  _serializeNode(nodeId, functionInfo, count, size, liveCount, liveSize, hasChildren) {
    return new HeapSnapshotModel.SerializedAllocationNode(
        nodeId, functionInfo.functionName, functionInfo.scriptName, functionInfo.scriptId, functionInfo.line,
        functionInfo.column, count, size, liveCount, liveSize, hasChildren);
  }
}

/**
 * @unrestricted
 */
export class TopDownAllocationNode {
  /**
   * @param {number} id
   * @param {!FunctionAllocationInfo} functionInfo
   * @param {number} count
   * @param {number} size
   * @param {number} liveCount
   * @param {number} liveSize
   * @param {?TopDownAllocationNode} parent
   */
  constructor(id, functionInfo, count, size, liveCount, liveSize, parent) {
    this.id = id;
    this.functionInfo = functionInfo;
    this.allocationCount = count;
    this.allocationSize = size;
    this.liveCount = liveCount;
    this.liveSize = liveSize;
    this.parent = parent;
    this.children = [];
  }
}

/**
 * @unrestricted
 */
export class BottomUpAllocationNode {
  /**
   * @param {!FunctionAllocationInfo} functionInfo
   */
  constructor(functionInfo) {
    this.functionInfo = functionInfo;
    this.allocationCount = 0;
    this.allocationSize = 0;
    this.liveCount = 0;
    this.liveSize = 0;
    this.traceTopIds = [];
    this._callers = [];
  }

  /**
   * @param {!TopDownAllocationNode} traceNode
   * @return {!BottomUpAllocationNode}
   */
  addCaller(traceNode) {
    const functionInfo = traceNode.functionInfo;
    let result;
    for (let i = 0; i < this._callers.length; i++) {
      const caller = this._callers[i];
      if (caller.functionInfo === functionInfo) {
        result = caller;
        break;
      }
    }
    if (!result) {
      result = new BottomUpAllocationNode(functionInfo);
      this._callers.push(result);
    }
    return result;
  }

  /**
   * @return {!Array.<!BottomUpAllocationNode>}
   */
  callers() {
    return this._callers;
  }

  /**
   * @return {boolean}
   */
  hasCallers() {
    return this._callers.length > 0;
  }
}

/**
 * @unrestricted
 */
export class FunctionAllocationInfo {
  /**
   * @param {string} functionName
   * @param {string} scriptName
   * @param {number} scriptId
   * @param {number} line
   * @param {number} column
   */
  constructor(functionName, scriptName, scriptId, line, column) {
    this.functionName = functionName;
    this.scriptName = scriptName;
    this.scriptId = scriptId;
    this.line = line;
    this.column = column;
    this.totalCount = 0;
    this.totalSize = 0;
    this.totalLiveCount = 0;
    this.totalLiveSize = 0;
    this._traceTops = [];
  }

  /**
   * @param {!TopDownAllocationNode} node
   */
  addTraceTopNode(node) {
    if (node.allocationCount === 0) {
      return;
    }
    this._traceTops.push(node);
    this.totalCount += node.allocationCount;
    this.totalSize += node.allocationSize;
    this.totalLiveCount += node.liveCount;
    this.totalLiveSize += node.liveSize;
  }

  /**
   * @return {?BottomUpAllocationNode}
   */
  bottomUpRoot() {
    if (!this._traceTops.length) {
      return null;
    }
    if (!this._bottomUpTree) {
      this._buildAllocationTraceTree();
    }
    return this._bottomUpTree;
  }

  _buildAllocationTraceTree() {
    this._bottomUpTree = new BottomUpAllocationNode(this);

    for (let i = 0; i < this._traceTops.length; i++) {
      let node = this._traceTops[i];
      let bottomUpNode = this._bottomUpTree;
      const count = node.allocationCount;
      const size = node.allocationSize;
      const liveCount = node.liveCount;
      const liveSize = node.liveSize;
      const traceId = node.id;
      while (true) {
        bottomUpNode.allocationCount += count;
        bottomUpNode.allocationSize += size;
        bottomUpNode.liveCount += liveCount;
        bottomUpNode.liveSize += liveSize;
        bottomUpNode.traceTopIds.push(traceId);
        node = node.parent;
        if (node === null) {
          break;
        }

        bottomUpNode = bottomUpNode.addCaller(node);
      }
    }
  }
}

/* Legacy exported object */
self.HeapSnapshotWorker = self.HeapSnapshotWorker || {};

/* Legacy exported object */
HeapSnapshotWorker = HeapSnapshotWorker || {};

/** @constructor */
HeapSnapshotWorker.AllocationProfile = AllocationProfile;

/** @constructor */
HeapSnapshotWorker.TopDownAllocationNode = TopDownAllocationNode;

/** @constructor */
HeapSnapshotWorker.BottomUpAllocationNode = BottomUpAllocationNode;

/** @constructor */
HeapSnapshotWorker.FunctionAllocationInfo = FunctionAllocationInfo;
