
#include "perf_data_converter.h"

#include <algorithm>
#include <limits>
#include <map>
#include <memory>
#include <set>
#include <unordered_map>

#include <android-base/logging.h>
#include <android-base/macros.h>
#include <android-base/strings.h>
#include <perf_data_utils.h>
#include <perf_parser.h>
#include <perf_protobuf_io.h>

#include "perfprofd_record.pb.h"
#include "perf_data.pb.h"

#include "map_utils.h"
#include "quipper_helper.h"
#include "symbolizer.h"

using std::map;

namespace android {
namespace perfprofd {

namespace {

void AddSymbolInfo(PerfprofdRecord* record,
                   ::quipper::PerfParser& perf_parser,
                   ::perfprofd::Symbolizer* symbolizer) {
  std::unordered_set<std::string> filenames_w_build_id;
  for (auto& perf_build_id : record->perf_data().build_ids()) {
    filenames_w_build_id.insert(perf_build_id.filename());
  }

  std::unordered_set<std::string> files_wo_build_id;
  {
    quipper::MmapEventIterator it(record->perf_data());
    for (; it != it.end(); ++it) {
      const ::quipper::PerfDataProto_MMapEvent* mmap_event = &it->mmap_event();
      if (!mmap_event->has_filename() || !mmap_event->has_start() || !mmap_event->has_len()) {
        // Don't care.
        continue;
      }
      if (filenames_w_build_id.count(mmap_event->filename()) == 0) {
        files_wo_build_id.insert(mmap_event->filename());
      }
    }
  }
  if (files_wo_build_id.empty()) {
    return;
  }

  struct Dso {
    uint64_t min_vaddr;
    RangeMap<std::string, uint64_t> symbols;
    explicit Dso(uint64_t min_vaddr_in) : min_vaddr(min_vaddr_in) {
    }
  };
  std::unordered_map<std::string, Dso> files;

  auto it = record->perf_data().events().begin();
  auto end = record->perf_data().events().end();
  auto parsed_it = perf_parser.parsed_events().begin();
  auto parsed_end = perf_parser.parsed_events().end();
  for (; it != end; ++it, ++parsed_it) {
    CHECK(parsed_it != parsed_end);
    if (!it->has_sample_event()) {
      continue;
    }

    const ::quipper::PerfDataProto_SampleEvent& sample_event = it->sample_event();

    if (android::base::kEnableDChecks) {
      // Check that the parsed_event and sample_event are consistent.
      CHECK_EQ(parsed_it->callchain.size(), sample_event.callchain_size());
    }

    auto check_address = [&](const std::string& dso_name, uint64_t offset) {
      if (files_wo_build_id.count(dso_name) == 0) {
        return;
      }

      // OK, that's a hit in the mmap segment (w/o build id).

      Dso* dso_data;
      {
        auto dso_it = files.find(dso_name);
        constexpr uint64_t kNoMinAddr = std::numeric_limits<uint64_t>::max();
        if (dso_it == files.end()) {
          uint64_t min_vaddr;
          bool has_min_vaddr = symbolizer->GetMinExecutableVAddr(dso_name, &min_vaddr);
          if (!has_min_vaddr) {
            min_vaddr = kNoMinAddr;
          }
          auto it = files.emplace(dso_name, Dso(min_vaddr));
          dso_data = &it.first->second;
        } else {
          dso_data = &dso_it->second;
        }
        if (dso_data->min_vaddr == kNoMinAddr) {
          return;
        }
      }

      // TODO: Is min_vaddr necessary here?
      const uint64_t file_addr = offset;

      std::string symbol = symbolizer->Decode(dso_name, file_addr);
      if (symbol.empty()) {
        return;
      }

      dso_data->symbols.Insert(symbol, file_addr);
    };
    if (sample_event.has_ip() && parsed_it->dso_and_offset.dso_info_ != nullptr) {
      check_address(parsed_it->dso_and_offset.dso_info_->name, parsed_it->dso_and_offset.offset_);
    }
    if (sample_event.callchain_size() > 0) {
      for (auto& callchain_data: parsed_it->callchain) {
        if (callchain_data.dso_info_ == nullptr) {
          continue;
        }
        check_address(callchain_data.dso_info_->name, callchain_data.offset_);
      }
    }
  }

  if (!files.empty()) {
    // We have extra symbol info, create proto messages now.
    for (auto& file_data : files) {
      const std::string& filename = file_data.first;
      const Dso& dso = file_data.second;
      if (dso.symbols.empty()) {
        continue;
      }

      PerfprofdRecord_SymbolInfo* symbol_info = record->add_symbol_info();
      symbol_info->set_filename(filename);
      symbol_info->set_filename_md5_prefix(::quipper::Md5Prefix(filename));
      symbol_info->set_min_vaddr(dso.min_vaddr);
      for (auto& aggr_sym : dso.symbols) {
        PerfprofdRecord_SymbolInfo_Symbol* symbol = symbol_info->add_symbols();
        symbol->set_addr(*aggr_sym.second.offsets.begin());
        symbol->set_size(*aggr_sym.second.offsets.rbegin() - *aggr_sym.second.offsets.begin() + 1);
        symbol->set_name(aggr_sym.second.symbol);
        symbol->set_name_md5_prefix(::quipper::Md5Prefix(aggr_sym.second.symbol));
      }
    }
  }
}

}  // namespace

PerfprofdRecord*
RawPerfDataToAndroidPerfProfile(const string &perf_file,
                                ::perfprofd::Symbolizer* symbolizer) {
  std::unique_ptr<PerfprofdRecord> ret(new PerfprofdRecord());
  ret->set_id(0);  // TODO.

  ::quipper::PerfParserOptions options = {};
  options.do_remap = true;
  options.discard_unused_events = true;
  options.read_missing_buildids = true;

  ::quipper::PerfDataProto* perf_data = ret->mutable_perf_data();

  ::quipper::PerfReader reader;
  if (!reader.ReadFile(perf_file)) return nullptr;

  ::quipper::PerfParser parser(&reader, options);
  if (!parser.ParseRawEvents()) return nullptr;

  if (!reader.Serialize(perf_data)) return nullptr;

  // Append parser stats to protobuf.
  ::quipper::PerfSerializer::SerializeParserStats(parser.stats(), perf_data);

  // TODO: Symbolization.
  if (symbolizer != nullptr) {
    AddSymbolInfo(ret.get(), parser, symbolizer);
  }

  return ret.release();
}

}  // namespace perfprofd
}  // namespace android
