/*
 * Copyright (C) 2025 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 <errno.h>
#include <string.h>
#include <sys/stat.h>

#include <iostream>
#include <memory>
#include <string_view>
#include <vector>

#include <memory_trace/TraceInfo.h>

#include "OpGenAnalysis.h"
#include "OpOverlapAnalysis.h"

namespace {

class OptionBase;

class OptionRegistry {
 public:
  static OptionRegistry& get() {
    static OptionRegistry registry;
    return registry;
  }

  void RegisterOption(OptionBase* opt) { options_.push_back(opt); }

  auto begin() { return options_.begin(); }
  auto end() { return options_.end(); }

  void Stream(std::ostream& os, std::string_view indent = "\t");

 private:
  OptionRegistry() {}

  std::vector<OptionBase*> options_;
};

class OptionBase {
 public:
  template <typename... Analyses>
  OptionBase(std::string_view name, std::string_view desc) : name_(name), desc_(desc) {
    OptionRegistry::get().RegisterOption(this);
  }

  std::string_view name() const { return name_; }
  std::string_view desc() const { return desc_; }

  void GetAnalyses(std::vector<Analysis*>& analyses) {
    for (auto& analysis : analyses_) analyses.push_back(analysis.get());
  }

 protected:
  template <typename Analysis, typename... Analyses,
            std::enable_if_t<(sizeof...(Analyses) > 0), bool> = true>
  void AppendAnalyses() {
    AppendAnalyses<Analysis>();
    AppendAnalyses<Analyses...>();
  }
  template <typename Analysis>
  void AppendAnalyses() {
    analyses_.push_back(std::move(std::make_unique<Analysis>()));
  }

  std::string_view name_;
  std::string_view desc_;
  std::vector<std::unique_ptr<Analysis>> analyses_;
};

template <typename... Analyses>
class Option : public OptionBase {
 public:
  Option(std::string_view name, std::string_view desc) : OptionBase(name, desc) {
    AppendAnalyses<Analyses...>();
  }
};

}  // namespace

void OptionRegistry::Stream(std::ostream& os, std::string_view indent) {
  for (OptionBase* opt : options_) {
    os << indent << "--" << opt->name() << ": " << opt->desc() << std::endl;
  }
}

static bool ParseArgs(int argc, char** argv, std::vector<Analysis*>& analyses,
                      std::vector<std::string>& traces) {
  auto& registry = OptionRegistry::get();
  for (int i = 0; i < argc; ++i) {
    if (argv[i][0] != '-') {
      traces.push_back(argv[i]);
      struct stat st;
      if (stat(traces.back().c_str(), &st) != 0) {
        if (errno == ENOENT) {
          std::cerr << traces.back() << " does not exist." << std::endl;
        } else {
          std::cerr << "stat of file " << traces.back() << " failed: " << strerror(errno)
                    << std::endl;
        }
        return false;
      }
      if (!S_ISREG(st.st_mode)) {
        std::cerr << traces.back() << " is not a regular file." << std::endl;
        return false;
      }
      continue;
    } else if (argv[i][1] != '-') {
      std::cerr << "Unknown option: " << argv[i] << std::endl;
      return false;
    }

    bool found = false;
    std::string_view arg(&argv[i][2]);
    for (auto* option : registry) {
      if (option->name() == arg) {
        option->GetAnalyses(analyses);
        found = true;
        break;
      }
    }
    if (!found) {
      std::cerr << "Unknown option: " << argv[i] << std::endl;
      return false;
    }
  }
  return true;
}

void Usage() {
  std::cerr << "Usage: memory_trace_analysis TRACE_FILE1 TRACE_FILE2 ... [Analyses...]\n";
  std::cerr << "Analyses:\n";
  OptionRegistry::get().Stream(std::cerr);
}

int main(int argc, char** argv) {
  static Option<OpMinMaxAnalysis, OpAverageAnalysis> gen(
      "op-gen-stats", "get the min/max/avg of each kind of alloc operation");
  static Option<OpOverlapAnalysis> overlap(
      "op-overlap", "get the amount of overlap in between each kind of alloc operation");

  if (argc < 2) {
    Usage();
    return 1;
  }

  std::vector<Analysis*> analyses;
  std::vector<std::string> traces;
  if (!ParseArgs(argc - 1, argv + 1, analyses, traces)) {
    Usage();
    return 1;
  }
  if (analyses.empty()) {
    std::cerr << "No analyses chosen.\n";
    Usage();
    return 1;
  }
  if (traces.empty()) {
    std::cerr << "No trace files.\n";
    Usage();
    return 1;
  }

  for (auto& trace : traces) {
    std::cout << "Analyzing trace " << trace << std::endl;
    memory_trace::TraceInfo info;
    info.Init(trace.c_str());
    for (auto& analysis : analyses) {
      std::cout << "  " << analysis->Name() << std::endl;
      analysis->Gather(info);
      analysis->StreamResult(std::cout, "    ");
    }
  }
  return 0;
}
