// Copyright 2015 The Weave 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 "src/commands/prop_constraints.h"

#include <base/json/json_writer.h>
#include <base/logging.h>

#include "src/commands/prop_values.h"
#include "src/commands/schema_constants.h"
#include "src/string_utils.h"

namespace weave {

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();
  CHECK(json);
  base::JSONWriter::Write(*json, &result);
  return result;
}

}  // anonymous namespace

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

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

void Constraint::AddToJsonDict(base::DictionaryValue* dict,
                               bool overridden_only) const {
  if (!overridden_only || HasOverriddenAttributes()) {
    auto value = ToJson();
    CHECK(value);
    dict->SetWithoutPathExpansion(GetDictKey(), value.release());
  }
}

// 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() const {
  return TypedValueToJson(limit_.value);
}

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

bool ConstraintStringLengthMin::Validate(const PropValue& value,
                                         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) {
      Error::AddTo(error, FROM_HERE, errors::commands::kDomain,
                   errors::commands::kOutOfRange, "String must not be empty");
    } else {
      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,
                                         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) {
    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<ValueVector> set)
    : set_(std::move(set)) {}
ConstraintOneOf::ConstraintOneOf(ValueVector set) : set_(std::move(set)) {}

bool ConstraintOneOf::Validate(const PropValue& value, 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<ValueVector> 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 {
  ValueVector 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() const {
  return TypedValueToJson(set_.value);
}

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

}  // namespace weave
