// Copyright 2014 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 "buffet/commands/prop_constraints.h"

#include <base/json/json_writer.h>

#include "buffet/commands/prop_values.h"
#include "buffet/commands/schema_constants.h"

namespace buffet {

namespace {

// Helper function to convert a property value to string, which is used for
// error reporting.
std::string PropValueToString(const PropValue& value) {
  std::string result;
  auto json = value.ToJson(nullptr);
  if (json)
    base::JSONWriter::Write(json.get(), &result);
  return result;
}

}  // anonymous namespace

// Constraint ----------------------------------------------------------------
Constraint::~Constraint() {}

bool Constraint::ReportErrorLessThan(chromeos::ErrorPtr* error,
                                     const std::string& val,
                                     const std::string& limit) {
  chromeos::Error::AddToPrintf(
      error, FROM_HERE, errors::commands::kDomain,
      errors::commands::kOutOfRange,
      "Value %s is out of range. It must not be less than %s",
      val.c_str(), limit.c_str());
  return false;
}

bool Constraint::ReportErrorGreaterThan(chromeos::ErrorPtr* error,
                                        const std::string& val,
                                        const std::string& limit) {
  chromeos::Error::AddToPrintf(
      error, FROM_HERE, errors::commands::kDomain,
      errors::commands::kOutOfRange,
      "Value %s is out of range. It must not be greater than %s",
      val.c_str(), limit.c_str());
  return false;
}

bool Constraint::ReportErrorNotOneOf(chromeos::ErrorPtr* error,
                                     const std::string& val,
                                     const std::vector<std::string>& values) {
  chromeos::Error::AddToPrintf(
      error, FROM_HERE, errors::commands::kDomain,
      errors::commands::kOutOfRange,
      "Value %s is invalid. Expected one of [%s]", val.c_str(),
      chromeos::string_utils::Join(",", values).c_str());
  return false;
}

bool Constraint::AddToJsonDict(base::DictionaryValue* dict,
                               bool overridden_only,
                               chromeos::ErrorPtr* error) const {
  if (!overridden_only || HasOverriddenAttributes()) {
    auto value = ToJson(error);
    if (!value)
      return false;
    dict->SetWithoutPathExpansion(GetDictKey(), value.release());
  }
  return true;
}

// ConstraintStringLength -----------------------------------------------------
ConstraintStringLength::ConstraintStringLength(
    const InheritableAttribute<int>& limit) : limit_(limit) {}
ConstraintStringLength::ConstraintStringLength(int limit) : limit_(limit) {}

bool ConstraintStringLength::HasOverriddenAttributes() const {
  return !limit_.is_inherited;
}

std::unique_ptr<base::Value> ConstraintStringLength::ToJson(
    chromeos::ErrorPtr* error) const {
  return TypedValueToJson(limit_.value, error);
}

// ConstraintStringLengthMin --------------------------------------------------
ConstraintStringLengthMin::ConstraintStringLengthMin(
    const InheritableAttribute<int>& limit) : ConstraintStringLength(limit) {}
ConstraintStringLengthMin::ConstraintStringLengthMin(int limit)
    : ConstraintStringLength(limit) {}

bool ConstraintStringLengthMin::Validate(const PropValue& value,
                                         chromeos::ErrorPtr* error) const {
  CHECK(value.GetString()) << "Expecting a string value for this constraint";
  const std::string& str = value.GetString()->GetValue();
  int length = static_cast<int>(str.size());
  if (length < limit_.value) {
    if (limit_.value == 1) {
      chromeos::Error::AddTo(error, FROM_HERE, errors::commands::kDomain,
                             errors::commands::kOutOfRange,
                             "String must not be empty");
    } else {
      chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
                                   errors::commands::kOutOfRange,
                                   "String must be at least %d characters long,"
                                   " actual length of string '%s' is %d",
                                   limit_.value, str.c_str(), length);
    }
    return false;
  }
  return true;
}

std::unique_ptr<Constraint>
ConstraintStringLengthMin::Clone() const {
  return std::unique_ptr<Constraint>{new ConstraintStringLengthMin{limit_}};
}

std::unique_ptr<Constraint>
ConstraintStringLengthMin::CloneAsInherited() const {
  return std::unique_ptr<Constraint>{
      new ConstraintStringLengthMin{limit_.value}};
}

// ConstraintStringLengthMax --------------------------------------------------
ConstraintStringLengthMax::ConstraintStringLengthMax(
    const InheritableAttribute<int>& limit) : ConstraintStringLength(limit) {}
ConstraintStringLengthMax::ConstraintStringLengthMax(int limit)
    : ConstraintStringLength(limit) {}

bool ConstraintStringLengthMax::Validate(const PropValue& value,
                                         chromeos::ErrorPtr* error) const {
  CHECK(value.GetString()) << "Expecting a string value for this constraint";
  const std::string& str = value.GetString()->GetValue();
  int length = static_cast<int>(str.size());
  if (length > limit_.value) {
    chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
                                 errors::commands::kOutOfRange,
                                 "String must be no more than %d character(s) "
                                 "long, actual length of string '%s' is %d",
                                 limit_.value, str.c_str(), length);
    return false;
  }
  return true;
}

std::unique_ptr<Constraint>
ConstraintStringLengthMax::Clone() const {
  return std::unique_ptr<Constraint>{new ConstraintStringLengthMax{limit_}};
}

std::unique_ptr<Constraint>
ConstraintStringLengthMax::CloneAsInherited() const {
  return std::unique_ptr<Constraint>{
      new ConstraintStringLengthMax{limit_.value}};
}

// ConstraintOneOf --------------------------------------------------
ConstraintOneOf::ConstraintOneOf(InheritableAttribute<native_types::Array> set)
    : set_(std::move(set)) {}
ConstraintOneOf::ConstraintOneOf(native_types::Array set)
    : set_(std::move(set)) {}

bool ConstraintOneOf::Validate(const PropValue& value,
                               chromeos::ErrorPtr* error) const {
  for (const auto& item : set_.value) {
    if (value.IsEqual(item.get()))
      return true;
  }
  std::vector<std::string> choice_list;
  choice_list.reserve(set_.value.size());
  for (const auto& item : set_.value) {
    choice_list.push_back(PropValueToString(*item));
  }
  return ReportErrorNotOneOf(error, PropValueToString(value), choice_list);
}

std::unique_ptr<Constraint> ConstraintOneOf::Clone() const {
  InheritableAttribute<native_types::Array> attr;
  attr.is_inherited = set_.is_inherited;
  attr.value.reserve(set_.value.size());
  for (const auto& prop_value : set_.value) {
    attr.value.push_back(prop_value->Clone());
  }
  return std::unique_ptr<Constraint>{new ConstraintOneOf{std::move(attr)}};
}

std::unique_ptr<Constraint> ConstraintOneOf::CloneAsInherited() const {
  native_types::Array cloned;
  cloned.reserve(set_.value.size());
  for (const auto& prop_value : set_.value) {
    cloned.push_back(prop_value->Clone());
  }
  return std::unique_ptr<Constraint>{new ConstraintOneOf{std::move(cloned)}};
}

std::unique_ptr<base::Value> ConstraintOneOf::ToJson(
    chromeos::ErrorPtr* error) const {
  return TypedValueToJson(set_.value, error);
}

const char* ConstraintOneOf::GetDictKey() const {
  return commands::attributes::kOneOf_Enum;
}

}  // namespace buffet
