/*
 * 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 "src/trace_processor/metadata_table.h"
#include "src/trace_processor/sqlite/sqlite_utils.h"
#include "src/trace_processor/storage_columns.h"
#include "src/trace_processor/storage_schema.h"

namespace perfetto {
namespace trace_processor {

MetadataTable::MetadataTable(sqlite3*, const TraceStorage* storage)
    : storage_(storage) {}

void MetadataTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
  SqliteTable::Register<MetadataTable>(db, storage, "metadata");
}

StorageSchema MetadataTable::CreateStorageSchema() {
  return StorageSchema::Builder()
      .AddColumn<StringColumn<MetadataKeyNameAccessor>>(
          "name", &storage_->metadata().keys())
      .AddColumn<StringColumn<MetadataKeyTypeAccessor>>(
          "key_type", &storage_->metadata().keys())
      .AddColumn<ValueColumn>("int_value", Variadic::Type::kInt, storage_)
      .AddColumn<ValueColumn>("str_value", Variadic::Type::kString, storage_)
      .Build({"name"});
}

uint32_t MetadataTable::RowCount() {
  return static_cast<uint32_t>(storage_->metadata().keys().size());
}

int MetadataTable::BestIndex(const QueryConstraints&, BestIndexInfo*) {
  return SQLITE_OK;
}

MetadataTable::MetadataKeyNameAccessor::MetadataKeyNameAccessor(
    const std::deque<metadata::KeyIDs>* keys)
    : keys_(keys) {}

MetadataTable::MetadataKeyNameAccessor::~MetadataKeyNameAccessor() = default;

MetadataTable::MetadataKeyTypeAccessor::MetadataKeyTypeAccessor(
    const std::deque<metadata::KeyIDs>* keys)
    : keys_(keys) {}

MetadataTable::MetadataKeyTypeAccessor::~MetadataKeyTypeAccessor() = default;

MetadataTable::ValueColumn::ValueColumn(std::string col_name,
                                        Variadic::Type type,
                                        const TraceStorage* storage)
    : StorageColumn(col_name, false /* hidden */),
      type_(type),
      storage_(storage) {
  PERFETTO_CHECK(type == Variadic::Type::kInt ||
                 type == Variadic::Type::kString);
}

void MetadataTable::ValueColumn::ReportResult(sqlite3_context* ctx,
                                              uint32_t row) const {
  const auto& metadata = storage_->metadata();
  auto value_type = metadata::kValueTypes[metadata.keys()[row]];
  if (value_type != type_) {
    sqlite3_result_null(ctx);
    return;
  }

  if (value_type == Variadic::Type::kInt) {
    sqlite_utils::ReportSqliteResult(ctx, metadata.values()[row].int_value);
    return;
  }
  if (value_type == Variadic::Type::kString) {
    const char* str =
        storage_->GetString(metadata.values()[row].string_value).c_str();
    sqlite3_result_text(ctx, str, -1, sqlite_utils::kSqliteStatic);
    return;
  }
  PERFETTO_FATAL("Unimplemented metadata value type.");
}

MetadataTable::ValueColumn::Bounds MetadataTable::ValueColumn::BoundFilter(
    int,
    sqlite3_value*) const {
  return Bounds{};
}

void MetadataTable::ValueColumn::Filter(int op,
                                        sqlite3_value* value,
                                        FilteredRowIndex* index) const {
  if (type_ == Variadic::Type::kInt) {
    bool op_is_null = sqlite_utils::IsOpIsNull(op);
    auto predicate = sqlite_utils::CreateNumericPredicate<int64_t>(op, value);
    index->FilterRows(
        [this, predicate, op_is_null](uint32_t row) PERFETTO_ALWAYS_INLINE {
          const auto& arg = storage_->metadata().values()[row];
          return arg.type == type_ ? predicate(arg.int_value) : op_is_null;
        });
    return;
  }
  if (type_ == Variadic::Type::kString) {
    auto predicate = sqlite_utils::CreateStringPredicate(op, value);
    index->FilterRows([this, &predicate](uint32_t row) PERFETTO_ALWAYS_INLINE {
      const auto& arg = storage_->metadata().values()[row];
      return arg.type == type_
                 ? predicate(storage_->GetString(arg.string_value).c_str())
                 : predicate(nullptr);
    });
    return;
  }
  PERFETTO_FATAL("Unimplemented metadata value type.");
}

MetadataTable::ValueColumn::Comparator MetadataTable::ValueColumn::Sort(
    const QueryConstraints::OrderBy& ob) const {
  if (ob.desc) {
    return [this](uint32_t f, uint32_t s) { return -CompareRefsAsc(f, s); };
  }
  return [this](uint32_t f, uint32_t s) { return CompareRefsAsc(f, s); };
}

int MetadataTable::ValueColumn::CompareRefsAsc(uint32_t f, uint32_t s) const {
  const auto& arg_f = storage_->metadata().values()[f];
  const auto& arg_s = storage_->metadata().values()[s];

  if (arg_f.type == type_ && arg_s.type == type_) {
    if (type_ == Variadic::Type::kInt) {
      return sqlite_utils::CompareValuesAsc(arg_f.int_value, arg_s.int_value);
    }
    if (type_ == Variadic::Type::kString) {
      const auto& f_str = storage_->GetString(arg_f.string_value);
      const auto& s_str = storage_->GetString(arg_s.string_value);
      return sqlite_utils::CompareValuesAsc(f_str, s_str);
    }
    PERFETTO_FATAL("Unimplemented metadata value type.");
  } else if (arg_s.type == type_) {
    return -1;
  } else if (arg_f.type == type_) {
    return 1;
  }
  return 0;
}

}  // namespace trace_processor
}  // namespace perfetto
