/*
 * Copyright (C) 2019 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 <stdio.h>

#include <memory>
#include <string>
#include <thread>
#include <vector>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <ziparchive/zip_writer.h>

#include "cmd_api_impl.h"
#include "command.h"
#include "environment.h"
#include "event_type.h"
#include "utils.h"
#include "workload.h"

namespace simpleperf {
namespace {

const std::string SIMPLEPERF_DATA_DIR = "simpleperf_data";

class PrepareCommand : public Command {
 public:
  PrepareCommand()
      : Command("api-prepare", "Prepare recording via app api", "Usage: simpleperf api-prepare\n") {
  }
  bool Run(const std::vector<std::string>& args);
};

bool PrepareCommand::Run(const std::vector<std::string>&) {
  // Enable profiling.
  if (!CheckPerfEventLimit()) {
    return false;
  }
  // Create tracepoint_events file.
  return EventTypeManager::Instance().WriteTracepointsToFile("/data/local/tmp/tracepoint_events");
}

class CollectCommand : public Command {
 public:
  CollectCommand()
      : Command("api-collect", "Collect recording data generated by app api",
                // clang-format off
"Usage: simpleperf api-collect [options]\n"
"--app <package_name>    the android application having recording data\n"
"-o record_zipfile_path  the path to store recording data\n"
"                        Default is simpleperf_data.zip.\n"
#if 0
// Below options are only used internally and shouldn't be visible to the public.
"--in-app               We are already running in the app's context.\n"
"--out-fd <fd>          Write output to a file descriptor.\n"
"--stop-signal-fd <fd>  Stop recording when fd is readable.\n"
#endif
                // clang-format on
        ) {
  }
  bool Run(const std::vector<std::string>& args);

 private:
  bool ParseOptions(const std::vector<std::string>& args);
  void HandleStopSignal();
  bool CollectRecordingData();
  bool RemoveRecordingData();

  std::string app_name_;
  std::string output_filepath_ = "simpleperf_data.zip";
  bool in_app_context_ = false;
  android::base::unique_fd out_fd_;
  android::base::unique_fd stop_signal_fd_;
};

bool CollectCommand::Run(const std::vector<std::string>& args) {
  if (!ParseOptions(args)) {
    return false;
  }
  if (in_app_context_) {
    HandleStopSignal();
    return CollectRecordingData() && RemoveRecordingData();
  }
  return RunInAppContext(app_name_, Name(), args, 0, output_filepath_, false);
}

bool CollectCommand::ParseOptions(const std::vector<std::string>& args) {
  OptionValueMap options;
  std::vector<std::pair<OptionName, OptionValue>> ordered_options;
  if (!PreprocessOptions(args, GetApiCollectCmdOptionFormats(), &options, &ordered_options,
                         nullptr)) {
    return false;
  }

  if (auto value = options.PullValue("--app"); value) {
    app_name_ = *value->str_value;
  }
  in_app_context_ = options.PullBoolValue("--in-app");

  if (auto value = options.PullValue("-o"); value) {
    output_filepath_ = *value->str_value;
  }
  if (auto value = options.PullValue("--out-fd"); value) {
    out_fd_.reset(static_cast<int>(value->uint_value));
  }
  if (auto value = options.PullValue("--stop-signal-fd"); value) {
    stop_signal_fd_.reset(static_cast<int>(value->uint_value));
  }

  CHECK(options.values.empty());
  CHECK(ordered_options.empty());
  if (!in_app_context_) {
    if (app_name_.empty()) {
      LOG(ERROR) << "--app is missing";
      return false;
    }
  }
  return true;
}

void CollectCommand::HandleStopSignal() {
  int fd = stop_signal_fd_.release();
  std::thread thread([fd]() {
    char c;
    static_cast<void>(read(fd, &c, 1));
    exit(1);
  });
  thread.detach();
}

bool CollectCommand::CollectRecordingData() {
  std::unique_ptr<FILE, decltype(&fclose)> fp(android::base::Fdopen(std::move(out_fd_), "w"),
                                              fclose);
  if (fp == nullptr) {
    PLOG(ERROR) << "failed to call fdopen";
    return false;
  }
  std::vector<char> buffer(64 * 1024);
  ZipWriter zip_writer(fp.get());
  for (const auto& name : GetEntriesInDir(SIMPLEPERF_DATA_DIR)) {
    // No need to collect temporary files.
    const std::string path = SIMPLEPERF_DATA_DIR + "/" + name;
    if (android::base::StartsWith(name, "TemporaryFile-") || !IsRegularFile(path)) {
      continue;
    }
    int result = zip_writer.StartEntry(name.c_str(), ZipWriter::kCompress);
    if (result != 0) {
      LOG(ERROR) << "failed to start zip entry " << name << ": "
                 << zip_writer.ErrorCodeString(result);
      return false;
    }
    android::base::unique_fd in_fd(FileHelper::OpenReadOnly(path));
    if (in_fd == -1) {
      PLOG(ERROR) << "failed to open " << path;
      return false;
    }
    while (true) {
      ssize_t nread = TEMP_FAILURE_RETRY(read(in_fd, buffer.data(), buffer.size()));
      if (nread < 0) {
        PLOG(ERROR) << "failed to read " << path;
        return false;
      }
      if (nread == 0) {
        break;
      }
      result = zip_writer.WriteBytes(buffer.data(), nread);
      if (result != 0) {
        LOG(ERROR) << "failed to write zip entry " << name << ": "
                   << zip_writer.ErrorCodeString(result);
        return false;
      }
    }
    result = zip_writer.FinishEntry();
    if (result != 0) {
      LOG(ERROR) << "failed to finish zip entry " << name << ": "
                 << zip_writer.ErrorCodeString(result);
      return false;
    }
  }
  int result = zip_writer.Finish();
  if (result != 0) {
    LOG(ERROR) << "failed to finish zip writer: " << zip_writer.ErrorCodeString(result);
    return false;
  }
  return true;
}

bool CollectCommand::RemoveRecordingData() {
  return Workload::RunCmd({"rm", "-rf", SIMPLEPERF_DATA_DIR});
}
}  // namespace

void RegisterAPICommands() {
  RegisterCommand("api-prepare", [] { return std::unique_ptr<Command>(new PrepareCommand()); });
  RegisterCommand("api-collect", [] { return std::unique_ptr<Command>(new CollectCommand()); });
}

}  // namespace simpleperf
