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

#ifndef TOOLS_JSON_SCHEMA_COMPILER_UTIL_H_
#define TOOLS_JSON_SCHEMA_COMPILER_UTIL_H_

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/format_macros.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"

namespace json_schema_compiler {

namespace util {

// Populates the item |out| from the value |from|. These are used by template
// specializations of |Get(Optional)ArrayFromList|.
bool PopulateItem(const base::Value& from, base::Value* out);

bool PopulateItem(const base::Value& from, int* out);
bool PopulateItem(const base::Value& from, int* out, std::u16string* error);
bool PopulateItem(const base::Value& from, bool* out);
bool PopulateItem(const base::Value& from, bool* out, std::u16string* error);
bool PopulateItem(const base::Value& from, double* out);
bool PopulateItem(const base::Value& from, double* out, std::u16string* error);
bool PopulateItem(const base::Value& from, std::string* out);
bool PopulateItem(const base::Value& from,
                  std::string* out,
                  std::u16string* error);
bool PopulateItem(const base::Value& from, std::vector<uint8_t>* out);
bool PopulateItem(const base::Value& from,
                  std::vector<uint8_t>* out,
                  std::u16string* error);
bool PopulateItem(const base::Value& from,
                  base::Value* out,
                  std::u16string* error);

// This template is used for types generated by tools/json_schema_compiler.
template <class T>
bool PopulateItem(const base::Value& from, T* out) {
  if (!from.is_dict())
    return false;
  T obj;
  if (!T::Populate(from, &obj))
    return false;
  *out = std::move(obj);
  return true;
}

// This template is used for types generated by tools/json_schema_compiler with
// error generation enabled.
template <class T>
bool PopulateItem(const base::Value& from, T* out, std::u16string* error) {
  T obj;
  if (!T::Populate(from, &obj, error))
    return false;
  *out = std::move(obj);
  return true;
}

// Populates |out| with |list|. Returns false if there is no list at the
// specified key or if the list has anything other than |T|.
template <class T>
bool PopulateArrayFromList(const base::Value::List& list, std::vector<T>* out) {
  out->clear();
  out->reserve(list.size());
  T item;
  for (const auto& value : list) {
    if (!PopulateItem(value, &item))
      return false;
    // T might not be movable, but in that case it should be copyable, and this
    // will still work.
    out->push_back(std::move(item));
  }

  return true;
}

// Populates |out| with |list|. Returns false and sets |error| if there is no
// list at the specified key or if the list has anything other than |T|.
template <class T>
bool PopulateArrayFromList(const base::Value::List& list,
                           std::vector<T>* out,
                           std::u16string* error) {
  out->clear();
  out->reserve(list.size());
  T item;
  std::u16string item_error;
  for (size_t i = 0; i < list.size(); ++i) {
    if (!PopulateItem(list[i], &item, &item_error)) {
      DCHECK(error->empty());
      *error = base::ASCIIToUTF16(
          base::StringPrintf("Parsing array failed at index %" PRIuS ": %s", i,
                             base::UTF16ToASCII(item_error).c_str()));
      return false;
    }
    out->push_back(std::move(item));
  }

  return true;
}

// Creates a new vector containing |list| at |out|. Returns
// true on success or if there is nothing at the specified key. Returns false
// if anything other than a list of |T| is at the specified key.
template <class T>
bool PopulateOptionalArrayFromList(const base::Value::List& list,
                                   absl::optional<std::vector<T>>* out) {
  std::vector<T> populated;
  if (!PopulateArrayFromList(list, &populated))
    return false;
  *out = std::move(populated);
  return true;
}

template <class T>
bool PopulateOptionalArrayFromList(const base::Value::List& list,
                                   absl::optional<std::vector<T>>* out,
                                   std::u16string* error) {
  std::vector<T> populated;
  if (!PopulateArrayFromList(list, &populated, error))
    return false;
  *out = std::move(populated);
  return true;
}

// Appends a Value newly created from |from| to |out|. These used by template
// specializations of |Set(Optional)ArrayToList|.
void AddItemToList(const int from, base::Value::List* out);
void AddItemToList(const bool from, base::Value::List* out);
void AddItemToList(const double from, base::Value::List* out);
void AddItemToList(const std::string& from, base::Value::List* out);
void AddItemToList(const std::vector<uint8_t>& from, base::Value::List* out);
void AddItemToList(const base::Value& from, base::Value::List* out);
void AddItemToList(const base::Value::Dict& from, base::Value::List* out);

// This template is used for types generated by tools/json_schema_compiler.
template <class T>
void AddItemToList(const std::unique_ptr<T>& from, base::Value::List* out) {
  out->Append(from->ToValue());
}

// This template is used for types generated by tools/json_schema_compiler.
template <class T>
void AddItemToList(const T& from, base::Value::List* out) {
  out->Append(from.ToValue());
}

// Set |out| to the the contents of |from|. Requires PopulateItem to be
// implemented for |T|.
template <class T>
void PopulateListFromArray(const std::vector<T>& from, base::Value::List* out) {
  out->clear();
  for (const T& item : from)
    AddItemToList(item, out);
}

// Set |out| to the the contents of |from| if |from| is not null. Requires
// PopulateItem to be implemented for |T|.
template <class T>
void PopulateListFromOptionalArray(const std::unique_ptr<std::vector<T>>& from,
                                   base::Value::List* out) {
  if (from)
    PopulateListFromArray(*from, out);
}

template <class T>
base::Value::List CreateValueFromArray(const std::vector<T>& from) {
  base::Value::List list;
  PopulateListFromArray(from, &list);
  return list;
}

}  // namespace util
}  // namespace json_schema_compiler

#endif  // TOOLS_JSON_SCHEMA_COMPILER_UTIL_H_
