/*
 * Copyright (C) 2015 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.
 */

#ifndef SIMPLE_PERF_CALLCHAIN_H_
#define SIMPLE_PERF_CALLCHAIN_H_

#include <string.h>

#include <algorithm>
#include <functional>
#include <memory>
#include <queue>
#include <vector>

#include <android-base/logging.h>

template <typename EntryT>
struct CallChainNode {
  uint64_t period;
  uint64_t children_period;
  std::vector<EntryT*> chain;
  std::vector<std::unique_ptr<CallChainNode>> children;
};

template <typename EntryT>
struct CallChainRoot {
  typedef CallChainNode<EntryT> NodeT;
  // If duplicated = true, this call tree is part of another call tree.
  // And we don't need to show it in brief callgraph report mode.
  bool duplicated;
  uint64_t children_period;
  std::vector<std::unique_ptr<NodeT>> children;

  CallChainRoot() : duplicated(false), children_period(0) {}

  void AddCallChain(
      const std::vector<EntryT*>& callchain, uint64_t period,
      std::function<bool(const EntryT*, const EntryT*)> is_same_sample) {
    children_period += period;
    NodeT* p = FindMatchingNode(children, callchain[0], is_same_sample);
    if (p == nullptr) {
      std::unique_ptr<NodeT> new_node = AllocateNode(callchain, 0, period, 0);
      children.push_back(std::move(new_node));
      return;
    }
    size_t callchain_pos = 0;
    while (true) {
      size_t match_length =
          GetMatchingLengthInNode(p, callchain, callchain_pos, is_same_sample);
      CHECK_GT(match_length, 0u);
      callchain_pos += match_length;
      bool find_child = true;
      if (match_length < p->chain.size()) {
        SplitNode(p, match_length);
        find_child = false;  // No need to find matching node in p->children.
      }
      if (callchain_pos == callchain.size()) {
        p->period += period;
        return;
      }
      p->children_period += period;
      if (find_child) {
        NodeT* np = FindMatchingNode(p->children, callchain[callchain_pos],
                                     is_same_sample);
        if (np != nullptr) {
          p = np;
          continue;
        }
      }
      std::unique_ptr<NodeT> new_node =
          AllocateNode(callchain, callchain_pos, period, 0);
      p->children.push_back(std::move(new_node));
      break;
    }
  }

  void SortByPeriod() {
    std::queue<std::vector<std::unique_ptr<NodeT>>*> queue;
    queue.push(&children);
    while (!queue.empty()) {
      std::vector<std::unique_ptr<NodeT>>* v = queue.front();
      queue.pop();
      std::sort(v->begin(), v->end(), CallChainRoot::CompareNodeByPeriod);
      for (auto& node : *v) {
        if (!node->children.empty()) {
          queue.push(&node->children);
        }
      }
    }
  }

 private:
  NodeT* FindMatchingNode(
      const std::vector<std::unique_ptr<NodeT>>& nodes, const EntryT* sample,
      std::function<bool(const EntryT*, const EntryT*)> is_same_sample) {
    for (auto& node : nodes) {
      if (is_same_sample(node->chain.front(), sample)) {
        return node.get();
      }
    }
    return nullptr;
  }

  size_t GetMatchingLengthInNode(
      NodeT* node, const std::vector<EntryT*>& chain, size_t chain_start,
      std::function<bool(const EntryT*, const EntryT*)> is_same_sample) {
    size_t i, j;
    for (i = 0, j = chain_start; i < node->chain.size() && j < chain.size();
         ++i, ++j) {
      if (!is_same_sample(node->chain[i], chain[j])) {
        break;
      }
    }
    return i;
  }

  void SplitNode(NodeT* parent, size_t parent_length) {
    std::unique_ptr<NodeT> child = AllocateNode(
        parent->chain, parent_length, parent->period, parent->children_period);
    child->children = std::move(parent->children);
    parent->period = 0;
    parent->children_period = child->period + child->children_period;
    parent->chain.resize(parent_length);
    parent->children.clear();
    parent->children.push_back(std::move(child));
  }

  std::unique_ptr<NodeT> AllocateNode(const std::vector<EntryT*>& chain,
                                      size_t chain_start, uint64_t period,
                                      uint64_t children_period) {
    std::unique_ptr<NodeT> node(new NodeT);
    for (size_t i = chain_start; i < chain.size(); ++i) {
      node->chain.push_back(chain[i]);
    }
    node->period = period;
    node->children_period = children_period;
    return node;
  }

  static bool CompareNodeByPeriod(const std::unique_ptr<NodeT>& n1,
                                  const std::unique_ptr<NodeT>& n2) {
    uint64_t period1 = n1->period + n1->children_period;
    uint64_t period2 = n2->period + n2->children_period;
    return period1 > period2;
  }
};

#endif  // SIMPLE_PERF_CALLCHAIN_H_
