/*
 * 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/trace_processor/thread_table.h"

#include "perfetto/base/logging.h"
#include "src/trace_processor/sqlite/query_constraints.h"
#include "src/trace_processor/sqlite/sqlite_utils.h"

namespace perfetto {
namespace trace_processor {

namespace {

using namespace sqlite_utils;

}  // namespace

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

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

util::Status ThreadTable::Init(int, const char* const*, Schema* schema) {
  *schema = Schema(
      {
          SqliteTable::Column(Column::kUtid, "utid", SqlValue::Type::kLong),
          SqliteTable::Column(Column::kUpid, "upid", SqlValue::Type::kLong),
          SqliteTable::Column(Column::kName, "name", SqlValue::Type::kString),
          SqliteTable::Column(Column::kTid, "tid", SqlValue::Type::kLong),
          SqliteTable::Column(Column::kStartTs, "start_ts",
                              SqlValue::Type::kLong),
          SqliteTable::Column(Column::kEndTs, "end_ts", SqlValue::Type::kLong),
      },
      {Column::kUtid});
  return util::OkStatus();
}

std::unique_ptr<SqliteTable::Cursor> ThreadTable::CreateCursor() {
  return std::unique_ptr<SqliteTable::Cursor>(new Cursor(this));
}

int ThreadTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
  info->estimated_cost = static_cast<uint32_t>(storage_->thread_count());

  // If the query has a constraint on the |utid| field, return a reduced cost
  // because we can do that filter efficiently.
  const auto& constraints = qc.constraints();
  for (const auto& cs : qc.constraints()) {
    if (cs.column == Column::kUtid) {
      info->estimated_cost = IsOpEq(constraints.front().op) ? 1 : 10;
    }
  }
  return SQLITE_OK;
}

ThreadTable::Cursor::Cursor(ThreadTable* table)
    : SqliteTable::Cursor(table), storage_(table->storage_), table_(table) {}

int ThreadTable::Cursor::Filter(const QueryConstraints& qc,
                                sqlite3_value** argv) {
  *this = Cursor(table_);

  min_ = 0;
  max_ = static_cast<uint32_t>(storage_->thread_count());
  desc_ = false;

  for (size_t j = 0; j < qc.constraints().size(); j++) {
    const auto& cs = qc.constraints()[j];
    if (cs.column == Column::kUtid) {
      UniqueTid constraint_utid =
          static_cast<UniqueTid>(sqlite3_value_int(argv[j]));
      // Filter the range of utids that we are interested in, based on the
      // constraints in the query. Everything between min and max (exclusive)
      // will be returned.
      if (IsOpEq(cs.op)) {
        min_ = constraint_utid;
        max_ = constraint_utid + 1;
      } else if (IsOpGe(cs.op) || IsOpGt(cs.op)) {
        min_ = IsOpGt(cs.op) ? constraint_utid + 1 : constraint_utid;
      } else if (IsOpLe(cs.op) || IsOpLt(cs.op)) {
        max_ = IsOpLt(cs.op) ? constraint_utid : constraint_utid + 1;
      }
    }
  }

  for (const auto& ob : qc.order_by()) {
    if (ob.iColumn == Column::kUtid) {
      desc_ = ob.desc;
    }
  }
  index_ = 0;

  return SQLITE_OK;
}

int ThreadTable::Cursor::Column(sqlite3_context* context, int N) {
  uint32_t current = desc_ ? max_ - index_ - 1 : min_ + index_;
  const auto& thread = storage_->GetThread(current);
  switch (N) {
    case Column::kUtid: {
      sqlite3_result_int64(context, current);
      break;
    }
    case Column::kUpid: {
      if (thread.upid.has_value()) {
        sqlite3_result_int64(context, thread.upid.value());
      } else {
        sqlite3_result_null(context);
      }
      break;
    }
    case Column::kName: {
      const auto& name = storage_->GetString(thread.name_id);
      sqlite3_result_text(context, name.c_str(), -1, kSqliteStatic);
      break;
    }
    case Column::kTid: {
      sqlite3_result_int64(context, thread.tid);
      break;
    }
    case Column::kStartTs: {
      if (thread.start_ns != 0) {
        sqlite3_result_int64(context, thread.start_ns);
      } else {
        sqlite3_result_null(context);
      }
      break;
    }
    case Column::kEndTs: {
      if (thread.end_ns != 0) {
        sqlite3_result_int64(context, thread.end_ns);
      } else {
        sqlite3_result_null(context);
      }
      break;
    }
    default: {
      PERFETTO_FATAL("Unknown column %d", N);
      break;
    }
  }
  return SQLITE_OK;
}

int ThreadTable::Cursor::Next() {
  ++index_;
  return SQLITE_OK;
}

int ThreadTable::Cursor::Eof() {
  return index_ >= (max_ - min_);
}
}  // namespace trace_processor
}  // namespace perfetto
