/*
 * 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 "command.h"
#include "event_type.h"
#include "environment.h"
#include "utils.h"
#include "workload.h"

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.
  if (!android::base::WriteStringToFile(GetTracepointEvents(),
                                        "/data/local/tmp/tracepoint_events")) {
    PLOG(ERROR) << "failed to write tracepoint_events file";
    return false;
  }
  return true;
}

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) {
  for (size_t i = 0; i < args.size(); ++i) {
    if (args[i] == "--app") {
      if (!NextArgumentOrError(args, &i)) {
        return false;
      }
      app_name_ = args[i];
    } else if (args[i] == "--in-app") {
      in_app_context_ = true;
    } else if (args[i] == "-o") {
      if (!NextArgumentOrError(args, &i)) {
        return false;
      }
      output_filepath_ = args[i];
    } else if (args[i] == "--out-fd") {
      int fd;
      if (!GetUintOption(args, &i, &fd)) {
        return false;
      }
      out_fd_.reset(fd);
    } else if (args[i] == "--stop-signal-fd") {
      int fd;
      if (!GetUintOption(args, &i, &fd)) {
        return false;
      }
      stop_signal_fd_.reset(fd);
    } else {
      ReportUnknownOption(args, i);
      return false;
    }
  }
  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()); });
}
