/*
 * 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.
 */

#include <inttypes.h>

#include <map>
#include <string>
#include <vector>

#include <base/logging.h>
#include <base/stringprintf.h>

#include "command.h"
#include "event_attr.h"
#include "record.h"
#include "record_file.h"

using namespace PerfFileFormat;

class DumpRecordCommandImpl {
 public:
  DumpRecordCommandImpl() : record_filename_("perf.data") {
  }

  bool Run(const std::vector<std::string>& args);

 private:
  bool ParseOptions(const std::vector<std::string>& args);
  void DumpFileHeader();
  void DumpAttrSection();
  void DumpDataSection();

  std::string record_filename_;
  std::unique_ptr<RecordFileReader> record_file_reader_;

  std::vector<int> features_;
};

bool DumpRecordCommandImpl::Run(const std::vector<std::string>& args) {
  if (!ParseOptions(args)) {
    return false;
  }
  record_file_reader_ = RecordFileReader::CreateInstance(record_filename_);
  if (record_file_reader_ == nullptr) {
    return false;
  }
  DumpFileHeader();
  DumpAttrSection();
  DumpDataSection();

  return true;
}

bool DumpRecordCommandImpl::ParseOptions(const std::vector<std::string>& args) {
  if (args.size() == 2) {
    record_filename_ = args[1];
  }
  return true;
}

static const std::string GetFeatureName(int feature);

void DumpRecordCommandImpl::DumpFileHeader() {
  const FileHeader* header = record_file_reader_->FileHeader();
  printf("magic: ");
  for (size_t i = 0; i < 8; ++i) {
    printf("%c", header->magic[i]);
  }
  printf("\n");
  printf("header_size: %" PRId64 "\n", header->header_size);
  if (header->header_size != sizeof(*header)) {
    PLOG(WARNING) << "record file header size doesn't match expected header size "
                  << sizeof(*header);
  }
  printf("attr_size: %" PRId64 "\n", header->attr_size);
  if (header->attr_size != sizeof(FileAttr)) {
    PLOG(WARNING) << "record file attr size doesn't match expected attr size " << sizeof(FileAttr);
  }
  printf("attrs[file section]: offset %" PRId64 ", size %" PRId64 "\n", header->attrs.offset,
         header->attrs.size);
  printf("data[file section]: offset %" PRId64 ", size %" PRId64 "\n", header->data.offset,
         header->data.size);
  printf("event_types[file section]: offset %" PRId64 ", size %" PRId64 "\n",
         header->event_types.offset, header->event_types.size);

  features_.clear();
  for (size_t i = 0; i < FEAT_MAX_NUM; ++i) {
    size_t j = i / 8;
    size_t k = i % 8;
    if ((header->features[j] & (1 << k)) != 0) {
      features_.push_back(i);
    }
  }
  for (auto& feature : features_) {
    printf("feature: %s\n", GetFeatureName(feature).c_str());
  }
}

static const std::string GetFeatureName(int feature) {
  static std::map<int, std::string> feature_name_map = {
      {FEAT_TRACING_DATA, "tracing_data"},
      {FEAT_BUILD_ID, "build_id"},
      {FEAT_HOSTNAME, "hostname"},
      {FEAT_OSRELEASE, "osrelease"},
      {FEAT_VERSION, "version"},
      {FEAT_ARCH, "arch"},
      {FEAT_NRCPUS, "nrcpus"},
      {FEAT_CPUDESC, "cpudesc"},
      {FEAT_CPUID, "cpuid"},
      {FEAT_TOTAL_MEM, "total_mem"},
      {FEAT_CMDLINE, "cmdline"},
      {FEAT_EVENT_DESC, "event_desc"},
      {FEAT_CPU_TOPOLOGY, "cpu_topology"},
      {FEAT_NUMA_TOPOLOGY, "numa_topology"},
      {FEAT_BRANCH_STACK, "branck_stack"},
      {FEAT_PMU_MAPPINGS, "pmu_mappings"},
      {FEAT_GROUP_DESC, "group_desc"},
  };
  auto it = feature_name_map.find(feature);
  if (it != feature_name_map.end()) {
    return it->second;
  }
  return android::base::StringPrintf("unknown_feature(%d)", feature);
}

void DumpRecordCommandImpl::DumpAttrSection() {
  std::vector<const FileAttr*> attrs = record_file_reader_->AttrSection();
  for (size_t i = 0; i < attrs.size(); ++i) {
    auto& attr = attrs[i];
    printf("file_attr %zu:\n", i + 1);
    DumpPerfEventAttr(attr->attr, 1);
    printf("  ids[file_section]: offset %" PRId64 ", size %" PRId64 "\n", attr->ids.offset,
           attr->ids.size);
    std::vector<uint64_t> ids = record_file_reader_->IdsForAttr(attr);
    if (ids.size() > 0) {
      printf("  ids:");
      for (auto& id : ids) {
        printf(" %" PRId64, id);
      }
      printf("\n");
    }
  }
}

void DumpRecordCommandImpl::DumpDataSection() {
  std::vector<std::unique_ptr<const Record>> records = record_file_reader_->DataSection();
  for (auto& record : records) {
    record->Dump();
  }
}

class DumpRecordCommand : public Command {
 public:
  DumpRecordCommand()
      : Command("dump", "dump perf record file",
                "Usage: simpleperf dumprecord [options] [perf_record_file]\n"
                "    Dump different parts of a perf record file. Default file is perf.data.\n") {
  }

  bool Run(const std::vector<std::string>& args) override {
    DumpRecordCommandImpl impl;
    return impl.Run(args);
  }
};

DumpRecordCommand dumprecord_cmd;
