// Copyright 2018 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/probe_result_checker.h"

#include <map>
#include <memory>
#include <string>
#include <utility>

#include <base/check.h>
#include <base/logging.h>
#include <base/values.h>

#include "runtime_probe/field_converter.h"

namespace runtime_probe {

namespace {
using ReturnCode = FieldConverter::ReturnCode;
}  // namespace

std::unique_ptr<ProbeResultChecker> ProbeResultChecker::FromValue(
    const base::Value& value) {
  if (value.is_dict())
    return ProbeResultCheckerDict::FromValue(value);
  if (value.is_list())
    return ProbeResultCheckerList::FromValue(value);
  LOG(ERROR) << "invalid type for 'expect' field: "
             << base::Value::GetTypeName(value.type());
  return nullptr;
}

std::unique_ptr<ProbeResultCheckerDict> ProbeResultCheckerDict::FromValue(
    const base::Value& dict_value) {
  auto instance = std::make_unique<ProbeResultCheckerDict>();
  for (const auto& entry : dict_value.DictItems()) {
    const auto& key = entry.first;
    const auto& val = entry.second;
    auto print_error_and_return = [&val]() {
      LOG(ERROR) << "'expect' attribute should be a list whose values are"
                 << "[<required:bool>, <expected_type:string>, "
                 << "<optional_validate_rule:string>], got: " << val;
      return nullptr;
    };

    const auto& list_value = val.GetList();

    if (list_value.size() < 2 || list_value.size() > 3)
      return print_error_and_return();

    if (!list_value[0].is_bool())
      return print_error_and_return();
    bool required = list_value[0].GetBool();
    auto* target =
        required ? &instance->required_fields_ : &instance->optional_fields_;

    if (!list_value[1].is_string())
      return print_error_and_return();
    const auto& expect_type = list_value[1].GetString();

    std::string validate_rule;
    if (list_value.size() == 3) {
      if (!list_value[2].is_string())
        return print_error_and_return();
      validate_rule = list_value[2].GetString();
    }

    std::unique_ptr<FieldConverter> converter = nullptr;
    if (expect_type == "str") {
      converter = StringFieldConverter::Build(validate_rule);
    } else if (expect_type == "int") {
      converter = IntegerFieldConverter::Build(validate_rule);
    } else if (expect_type == "double") {
      converter = DoubleFieldConverter::Build(validate_rule);
    } else if (expect_type == "hex") {
      converter = HexFieldConverter::Build(validate_rule);
    }

    if (converter == nullptr) {
      LOG(ERROR) << "Cannot build converter, 'expect_type': " << expect_type
                 << ", 'validate_rule': " << validate_rule;
      return nullptr;
    } else {
      (*target)[key] = std::move(converter);
    }
  }

  return instance;
}

bool ProbeResultCheckerDict::Apply(base::Value* probe_result) const {
  bool success = true;

  CHECK(probe_result != nullptr);

  // Try to convert and validate each required fields.
  // Any failures will cause the final result be |false|.
  for (const auto& entry : required_fields_) {
    const auto& key = entry.first;
    const auto& converter = entry.second;
    if (!probe_result->FindKey(key)) {
      DVLOG(2) << "Missing key: " << key;
      success = false;
      break;
    }

    auto return_code = converter->Convert(key, probe_result);
    if (return_code != ReturnCode::OK) {
      auto* value = probe_result->FindKey(key);
      LOG(ERROR) << "Failed to apply " << converter->ToString() << " on "
                 << *value << "(ReturnCode = " << static_cast<int>(return_code)
                 << ")";

      success = false;
      break;
    }
  }

  // |ProbeStatement| will remove this element from final results, there is no
  // need to continue.
  if (!success) {
    VLOG(3) << "probe_result = " << *probe_result;
    return false;
  }

  // Try to convert and validate each optional fields.
  // For failures, just remove them from probe_result and continue.
  for (const auto& entry : optional_fields_) {
    const auto& key = entry.first;
    const auto& converter = entry.second;
    if (!probe_result->FindKey(key))
      continue;

    auto return_code = converter->Convert(key, probe_result);
    if (return_code != ReturnCode::OK) {
      VLOG(1) << "Optional field '" << key << "' has unexpected value, "
              << "remove it from probe result.";
      probe_result->RemoveKey(key);
    }
  }

  // Now all fields should have the correct type, let's validate them.
  for (const auto& entry : required_fields_) {
    auto return_code = entry.second->Validate(entry.first, probe_result);
    if (return_code != ReturnCode::OK) {
      success = false;
      break;
    }
  }
  // Optional fields shouldn't have expect value.

  return success;
}

std::unique_ptr<ProbeResultCheckerList> ProbeResultCheckerList::FromValue(
    const base::Value& list_value) {
  auto instance = std::make_unique<ProbeResultCheckerList>();
  for (auto& dv : list_value.GetList()) {
    if (!dv.is_dict()) {
      LOG(ERROR) << "checker should be a valid dictionary";
      return nullptr;
    }
    auto checker = ProbeResultCheckerDict::FromValue(dv);
    if (!checker)
      return nullptr;
    instance->checkers.push_back(std::move(checker));
  }
  return instance;
}

bool ProbeResultCheckerList::Apply(base::Value* probe_result) const {
  if (checkers.size() == 0)
    return true;
  for (const auto& checker : checkers) {
    if (checker->Apply(probe_result))
      return true;
  }
  return false;
}

}  // namespace runtime_probe
