// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "runtime_probe/field_converter.h"

#include <inttypes.h>

#include <memory>

#include <base/check.h>
#include <base/strings/stringprintf.h>
#include <base/strings/string_number_conversions.h>
#include <base/values.h>

namespace runtime_probe {

namespace {
using ReturnCode = FieldConverter::ReturnCode;

constexpr const char* GetPrefix(ValidatorOperator op) {
  switch (op) {
    case ValidatorOperator::NOP:
      return "!nop ";
    case ValidatorOperator::RE:
      return "!re ";
    case ValidatorOperator::EQ:
      return "!eq ";
    case ValidatorOperator::NE:
      return "!ne ";
    case ValidatorOperator::GT:
      return "!gt ";
    case ValidatorOperator::GE:
      return "!ge ";
    case ValidatorOperator::LT:
      return "!lt ";
    case ValidatorOperator::LE:
      return "!le ";
    default:
      DCHECK(false) << "should never reach here";
  }
  return nullptr;
}

constexpr const char* ToString(ValidatorOperator op) {
  switch (op) {
    case ValidatorOperator::NOP:
      return "NOP";
    case ValidatorOperator::RE:
      return "RE";
    case ValidatorOperator::EQ:
      return "EQ";
    case ValidatorOperator::NE:
      return "NE";
    case ValidatorOperator::GT:
      return "GT";
    case ValidatorOperator::GE:
      return "GE";
    case ValidatorOperator::LT:
      return "LT";
    case ValidatorOperator::LE:
      return "LE";
    default:
      DCHECK(false) << "should never reach here";
  }
  return nullptr;
}

bool SplitValidateRuleString(const base::StringPiece& validate_rule,
                             ValidatorOperator* operator_,
                             base::StringPiece* operand) {
  if (validate_rule.empty()) {
    *operator_ = ValidatorOperator::NOP;
    *operand = "";
    return true;
  }

  auto first_space_idx = validate_rule.find_first_of(' ');
  auto prefix = validate_rule.substr(0, first_space_idx + 1);
  auto rest = validate_rule.substr(first_space_idx + 1);

  for (int i = 0; i < static_cast<int>(ValidatorOperator::NUM_OP); i++) {
    auto op = static_cast<ValidatorOperator>(i);
    if (prefix == GetPrefix(op)) {
      *operator_ = op;
      if (op != ValidatorOperator::NOP)  // NOP shouldn't have operand.
        *operand = rest;
      return true;
    }
  }
  return false;
}

template <typename ConverterType>
std::unique_ptr<ConverterType> BuildNumericConverter(
    const base::StringPiece& validate_rule) {
  ValidatorOperator op;
  base::StringPiece rest;

  if (SplitValidateRuleString(validate_rule, &op, &rest)) {
    if (op == ValidatorOperator::NOP)
      return std::make_unique<ConverterType>(op, 0);

    if (op == ValidatorOperator::EQ || op == ValidatorOperator::NE ||
        op == ValidatorOperator::GT || op == ValidatorOperator::GE ||
        op == ValidatorOperator::LT || op == ValidatorOperator::LE) {
      typename ConverterType::OperandType operand;
      if (ConverterType::StringToOperand(rest.as_string(), &operand)) {
        return std::make_unique<ConverterType>(op, operand);
      } else {
        LOG(ERROR) << "Can't convert to operand: " << rest.as_string();
      }
    }
  }
  LOG(ERROR) << "Invalid validate rule: " << validate_rule;
  return nullptr;
}

template <typename ValueType>
ReturnCode CheckNumber(ValidatorOperator op,
                       const ValueType lhs,
                       const ValueType rhs) {
  bool is_valid = true;
  switch (op) {
    case ValidatorOperator::NOP:
      break;
    case ValidatorOperator::EQ:
      is_valid = lhs == rhs;
      break;
    case ValidatorOperator::GE:
      is_valid = lhs >= rhs;
      break;
    case ValidatorOperator::GT:
      is_valid = lhs > rhs;
      break;
    case ValidatorOperator::LE:
      is_valid = lhs <= rhs;
      break;
    case ValidatorOperator::LT:
      is_valid = lhs < rhs;
      break;
    case ValidatorOperator::NE:
      is_valid = lhs != rhs;
      break;
    default:
      return ReturnCode::UNSUPPORTED_OPERATOR;
  }
  return is_valid ? ReturnCode::OK : ReturnCode::INVALID_VALUE;
}

}  // namespace

std::string StringFieldConverter::ToString() const {
  return base::StringPrintf("StringFieldConverter(%s, %s)",
                            ::runtime_probe::ToString(operator_),
                            operand_.c_str());
}

std::string IntegerFieldConverter::ToString() const {
  return base::StringPrintf("IntegerFieldConverter(%s, %d)",
                            ::runtime_probe::ToString(operator_), operand_);
}

std::string HexFieldConverter::ToString() const {
  return base::StringPrintf("HexFieldConverter(%s, 0x%" PRIx64 ")",
                            ::runtime_probe::ToString(operator_), operand_);
}

std::string DoubleFieldConverter::ToString() const {
  return base::StringPrintf("DoubleFieldConverter(%s, %f)",
                            ::runtime_probe::ToString(operator_), operand_);
}

std::unique_ptr<StringFieldConverter> StringFieldConverter::Build(
    const base::StringPiece& validate_rule) {
  ValidatorOperator op;
  base::StringPiece pattern;

  if (SplitValidateRuleString(validate_rule, &op, &pattern)) {
    if (op == ValidatorOperator::NOP)
      return std::make_unique<StringFieldConverter>(op, "");

    if (op == ValidatorOperator::EQ || op == ValidatorOperator::NE) {
      return std::make_unique<StringFieldConverter>(op, pattern);
    }

    if (op == ValidatorOperator::RE) {
      auto instance = std::make_unique<StringFieldConverter>(op, pattern);
      if (instance->regex_->error().empty()) {
        // No error, the pattern is valid.
        return instance;
      }
      // Error string is set to non-empty if there are errors.
      LOG(ERROR) << "Invalid pattern: " << pattern;
      LOG(ERROR) << instance->regex_->error();
    }
  }

  LOG(ERROR) << "Invalid validate rule: " << validate_rule;
  return nullptr;
}

std::unique_ptr<IntegerFieldConverter> IntegerFieldConverter::Build(
    const base::StringPiece& validate_rule) {
  return BuildNumericConverter<IntegerFieldConverter>(validate_rule);
}

std::unique_ptr<HexFieldConverter> HexFieldConverter::Build(
    const base::StringPiece& validate_rule) {
  return BuildNumericConverter<HexFieldConverter>(validate_rule);
}

std::unique_ptr<DoubleFieldConverter> DoubleFieldConverter::Build(
    const base::StringPiece& validate_rule) {
  return BuildNumericConverter<DoubleFieldConverter>(validate_rule);
}

ReturnCode StringFieldConverter::Convert(const std::string& field_name,
                                         base::Value* dict_value) const {
  CHECK(dict_value);

  auto* value = dict_value->FindKey(field_name);
  if (!value)
    return ReturnCode::FIELD_NOT_FOUND;

  switch (value->type()) {
    case base::Value::Type::DOUBLE:
      dict_value->SetStringKey(field_name, std::to_string(value->GetDouble()));
      return ReturnCode::OK;
    case base::Value::Type::INTEGER:
      dict_value->SetStringKey(field_name, std::to_string(value->GetInt()));
      return ReturnCode::OK;
    case base::Value::Type::NONE:
      dict_value->SetStringKey(field_name, "null");
      return ReturnCode::OK;
    case base::Value::Type::STRING:
      return ReturnCode::OK;
    default:
      return ReturnCode::INCOMPATIBLE_VALUE;
  }
}

ReturnCode IntegerFieldConverter::Convert(const std::string& field_name,
                                          base::Value* dict_value) const {
  CHECK(dict_value);

  auto* value = dict_value->FindKey(field_name);
  if (!value)
    return ReturnCode::FIELD_NOT_FOUND;

  switch (value->type()) {
    case base::Value::Type::DOUBLE:
      dict_value->SetIntKey(field_name, static_cast<int>(value->GetDouble()));
      return ReturnCode::OK;
    case base::Value::Type::INTEGER:
      return ReturnCode::OK;
    case base::Value::Type::STRING: {
      const auto& string_value = value->GetString();
      OperandType int_value;
      if (StringToOperand(string_value, &int_value)) {
        dict_value->SetIntKey(field_name, int_value);
        return ReturnCode::OK;
      } else {
        LOG(ERROR) << "Failed to convert '" << string_value << "' to integer.";
        return ReturnCode::INCOMPATIBLE_VALUE;
      }
    }
    default:
      return ReturnCode::INCOMPATIBLE_VALUE;
  }
}

ReturnCode HexFieldConverter::Convert(const std::string& field_name,
                                      base::Value* dict_value) const {
  CHECK(dict_value);

  auto* value = dict_value->FindKey(field_name);
  if (!value)
    return ReturnCode::FIELD_NOT_FOUND;

  OperandType int_value;
  switch (value->type()) {
    case base::Value::Type::DOUBLE:
      dict_value->SetIntKey(field_name, static_cast<int>(value->GetDouble()));
      return ReturnCode::OK;
    case base::Value::Type::INTEGER: {
      int_value = value->GetInt();
      break;
    }
    case base::Value::Type::STRING: {
      const auto& string_value_ = value->GetString();
      if (!StringToOperand(string_value_, &int_value)) {
        LOG(ERROR) << "Failed to convert '" << string_value_ << "' to integer.";
        return ReturnCode::INCOMPATIBLE_VALUE;
      }
      break;
    }
    default:
      return ReturnCode::INCOMPATIBLE_VALUE;
  }
  // Since base::Value only supports 32-bit integer, we use string field to
  // store large integers.  We convert values to decimal strings to make
  // google::protobuf::util::JsonStringToMessage parse strings to integers
  // correctly.
  const auto string_value = base::NumberToString(int_value);
  dict_value->SetStringKey(field_name, string_value);
  return ReturnCode::OK;
}

ReturnCode DoubleFieldConverter::Convert(const std::string& field_name,
                                         base::Value* dict_value) const {
  CHECK(dict_value);

  auto* value = dict_value->FindKey(field_name);
  if (!value)
    return ReturnCode::FIELD_NOT_FOUND;

  switch (value->type()) {
    case base::Value::Type::DOUBLE:
      return ReturnCode::OK;
    case base::Value::Type::INTEGER:
      dict_value->SetDoubleKey(field_name, value->GetDouble());
      return ReturnCode::OK;
    case base::Value::Type::STRING: {
      const auto& string_value = value->GetString();
      double double_value;
      if (StringToDouble(string_value, &double_value)) {
        dict_value->SetDoubleKey(field_name, double_value);
        return ReturnCode::OK;
      } else {
        LOG(ERROR) << "Failed to convert '" << string_value << "' to double.";
        return ReturnCode::INCOMPATIBLE_VALUE;
      }
    }
    default:
      return ReturnCode::INCOMPATIBLE_VALUE;
  }
}

ReturnCode StringFieldConverter::Validate(const std::string& field_name,
                                          base::Value* dict_value) const {
  CHECK(dict_value);

  auto* value_ = dict_value->FindKey(field_name);
  if (!value_)
    return ReturnCode::FIELD_NOT_FOUND;
  if (!value_->is_string())
    return ReturnCode::INCOMPATIBLE_VALUE;

  const auto& value = value_->GetString();
  bool is_valid = true;
  switch (operator_) {
    case ValidatorOperator::NOP:
      break;
    case ValidatorOperator::EQ:
      is_valid = value == operand_;
      break;
    case ValidatorOperator::RE:
      is_valid = regex_->FullMatch(value);
      break;
    case ValidatorOperator::NE:
      is_valid = value != operand_;
      break;
    default:
      return ReturnCode::UNSUPPORTED_OPERATOR;
  }
  return is_valid ? ReturnCode::OK : ReturnCode::INVALID_VALUE;
}

ReturnCode IntegerFieldConverter::Validate(const std::string& field_name,
                                           base::Value* dict_value) const {
  CHECK(dict_value);

  auto* value_ = dict_value->FindKey(field_name);
  if (!value_)
    return ReturnCode::FIELD_NOT_FOUND;
  if (!value_->is_int())
    return ReturnCode::INCOMPATIBLE_VALUE;
  const auto value = value_->GetInt();

  return CheckNumber(operator_, value, operand_);
}

ReturnCode HexFieldConverter::Validate(const std::string& field_name,
                                       base::Value* dict_value) const {
  CHECK(dict_value);

  auto* value_ = dict_value->FindKey(field_name);
  if (!value_)
    return ReturnCode::FIELD_NOT_FOUND;
  OperandType value;
  switch (value_->type()) {
    case base::Value::Type::INTEGER: {
      value = value_->GetInt();
      break;
    }
    case base::Value::Type::STRING: {
      const auto& string_value = value_->GetString();
      if (!StringToInt64(string_value, &value))
        return ReturnCode::INCOMPATIBLE_VALUE;
      break;
    }
    default:
      return ReturnCode::INCOMPATIBLE_VALUE;
  }
  return CheckNumber(operator_, value, operand_);
}

ReturnCode DoubleFieldConverter::Validate(const std::string& field_name,
                                          base::Value* dict_value) const {
  CHECK(dict_value);

  auto* value_ = dict_value->FindKey(field_name);
  if (!value_)
    return ReturnCode::FIELD_NOT_FOUND;
  if (!value_->is_double() && !value_->is_int())
    return ReturnCode::INCOMPATIBLE_VALUE;
  const auto value = value_->GetDouble();

  return CheckNumber(operator_, value, operand_);
}

}  // namespace runtime_probe
