/*
 * Copyright (C) 2018 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 "src/perfetto_cmd/config.h"

#include <stdlib.h>

#include "perfetto/base/logging.h"
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/tracing/core/data_source_config.h"
#include "perfetto/tracing/core/trace_config.h"

#include "protos/perfetto/config/ftrace/ftrace_config.gen.h"

namespace perfetto {
namespace {
using ValueUnit = std::pair<uint64_t, std::string>;
using UnitMultipler = std::pair<const char*, uint64_t>;

bool SplitValueAndUnit(const std::string& arg, ValueUnit* out) {
  char* end;
  if (arg.empty())
    return false;
  out->first = strtoull(arg.c_str(), &end, 10);
  if (end == arg.data())
    return false;
  std::string unit = arg.substr(static_cast<size_t>(end - arg.data()));
  out->second = std::move(unit);
  return true;
}

bool ConvertValue(const std::string& arg,
                  std::vector<UnitMultipler> units,
                  uint64_t* out) {
  if (arg.empty()) {
    *out = 0;
    return true;
  }

  if (arg == "0") {
    *out = 0;
    return true;
  }

  ValueUnit value_unit{};
  if (!SplitValueAndUnit(arg, &value_unit))
    return false;

  for (const auto& unit_multiplier : units) {
    if (value_unit.second != unit_multiplier.first)
      continue;
    *out = value_unit.first * unit_multiplier.second;
    return true;
  }
  return false;
}

bool ConvertTimeToMs(const std::string& arg, uint64_t* out) {
  return ConvertValue(
      arg,
      {
          {"ms", 1}, {"s", 1000}, {"m", 1000 * 60}, {"h", 1000 * 60 * 60},
      },
      out);
}

bool ConvertSizeToKb(const std::string& arg, uint64_t* out) {
  return ConvertValue(arg,
                      {
                          {"kb", 1},
                          {"mb", 1024},
                          {"gb", 1024 * 1024},
                          {"k", 1},
                          {"m", 1024},
                          {"g", 1024 * 1024},
                      },
                      out);
}

}  // namespace

bool CreateConfigFromOptions(const ConfigOptions& options,
                             TraceConfig* config) {
  uint64_t duration_ms = 0;
  if (!ConvertTimeToMs(options.time, &duration_ms)) {
    PERFETTO_ELOG("--time argument is invalid");
    return false;
  }

  uint64_t buffer_size_kb = 0;
  if (!ConvertSizeToKb(options.buffer_size, &buffer_size_kb)) {
    PERFETTO_ELOG("--buffer argument is invalid");
    return false;
  }

  uint64_t max_file_size_kb = 0;
  if (!ConvertSizeToKb(options.max_file_size, &max_file_size_kb)) {
    PERFETTO_ELOG("--size argument is invalid");
    return false;
  }

  std::vector<std::string> ftrace_events;
  std::vector<std::string> atrace_categories;
  std::vector<std::string> atrace_apps = options.atrace_apps;

  for (const auto& category : options.categories) {
    if (base::Contains(category, '/')) {
      ftrace_events.push_back(category);
    } else {
      atrace_categories.push_back(category);
    }

    // For the gfx category, also add the frame timeline data source
    // as it's very useful for debugging gfx issues.
    if (category == "gfx") {
      auto* frame_timeline = config->add_data_sources();
      frame_timeline->mutable_config()->set_name(
          "android.surfaceflinger.frametimeline");
    }
  }

  config->set_duration_ms(static_cast<unsigned int>(duration_ms));
  config->set_max_file_size_bytes(max_file_size_kb * 1024);
  config->set_flush_period_ms(30 * 1000);
  if (max_file_size_kb)
    config->set_write_into_file(true);
  config->add_buffers()->set_size_kb(static_cast<unsigned int>(buffer_size_kb));
  auto* ds_config = config->add_data_sources()->mutable_config();
  ds_config->set_name("linux.ftrace");
  protos::gen::FtraceConfig ftrace_cfg;
  for (const auto& evt : ftrace_events)
    ftrace_cfg.add_ftrace_events(evt);
  for (const auto& cat : atrace_categories)
    ftrace_cfg.add_atrace_categories(cat);
  for (const auto& app : atrace_apps)
    ftrace_cfg.add_atrace_apps(app);
  ftrace_cfg.set_symbolize_ksyms(true);
  ds_config->set_ftrace_config_raw(ftrace_cfg.SerializeAsString());

  auto* ps_config = config->add_data_sources()->mutable_config();
  ps_config->set_name("linux.process_stats");
  ps_config->set_target_buffer(0);

  return true;
}

}  // namespace perfetto
