// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// 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 <string>
#include <vector>

#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
#include "base/values.h"

namespace json_schema_compiler {

namespace util {

// Creates a new item at |out| from |from|[|index|]. These are used by template
// specializations of |Get(Optional)ArrayFromList|.
bool GetItemFromList(const base::ListValue& from, int index, int* out);
bool GetItemFromList(const base::ListValue& from, int index, bool* out);
bool GetItemFromList(const base::ListValue& from, int index, double* out);
bool GetItemFromList(const base::ListValue& from, int index, std::string* out);
bool GetItemFromList(const base::ListValue& from,
                     int index,
                     linked_ptr<base::Value>* out);
bool GetItemFromList(const base::ListValue& from,
                     int index,
                     linked_ptr<base::DictionaryValue>* out);

// This template is used for types generated by tools/json_schema_compiler.
template<class T>
bool GetItemFromList(const base::ListValue& from,
                     int index,
                     linked_ptr<T>* out) {
  const base::DictionaryValue* dict;
  if (!from.GetDictionary(index, &dict))
    return false;
  scoped_ptr<T> obj(new T());
  if (!T::Populate(*dict, obj.get()))
    return false;
  *out = linked_ptr<T>(obj.release());
  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::ListValue& list, std::vector<T>* out) {
  out->clear();
  T value;
  for (size_t i = 0; i < list.GetSize(); ++i) {
    if (!GetItemFromList(list, i, &value))
      return false;
    out->push_back(value);
  }

  return true;
}

// Populates |out| with |from|.|name|. Returns false if there is no list at
// the specified key or if the list has anything other than |T|.
template <class T>
bool PopulateArrayFromDictionary(
    const base::DictionaryValue& from,
    const std::string& name,
    std::vector<T>* out) {
  const base::ListValue* list = NULL;
  if (!from.GetListWithoutPathExpansion(name, &list))
    return false;

  return PopulateArrayFromList(*list, out);
}

// 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::ListValue& list,
    scoped_ptr<std::vector<T> >* out) {
  out->reset(new std::vector<T>());
  T value;
  for (size_t i = 0; i < list.GetSize(); ++i) {
    if (!GetItemFromList(list, i, &value)) {
      out->reset();
      return false;
    }
    (*out)->push_back(value);
  }

  return true;
}

// Creates a new vector containing |from|.|name| 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 PopulateOptionalArrayFromDictionary(
    const base::DictionaryValue& from,
    const std::string& name,
    scoped_ptr<std::vector<T> >* out) {
  const base::ListValue* list = NULL;
  {
    const base::Value* maybe_list = NULL;
    // Since |name| is optional, its absence is acceptable. However, anything
    // other than a ListValue is not.
    if (!from.GetWithoutPathExpansion(name, &maybe_list))
      return true;
    if (!maybe_list->IsType(base::Value::TYPE_LIST))
      return false;
    list = static_cast<const base::ListValue*>(maybe_list);
  }

  return PopulateOptionalArrayFromList(*list, out);
}

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

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

// Set |out| to the the contents of |from|. Requires GetItemFromList to be
// implemented for |T|.
template <class T>
void PopulateListFromArray(
    const std::vector<T>& from,
    base::ListValue* out) {
  out->Clear();
  for (typename std::vector<T>::const_iterator it = from.begin();
      it != from.end(); ++it) {
    AddItemToList(*it, out);
  }
}

// Set |out| to the the contents of |from| if |from| is non-NULL. Requires
// GetItemFromList to be implemented for |T|.
template <class T>
void PopulateListFromOptionalArray(
    const scoped_ptr<std::vector<T> >& from,
    base::ListValue* out) {
  if (from.get())
    PopulateListFromArray(*from, out);

}

template <class T>
scoped_ptr<base::Value> CreateValueFromArray(const std::vector<T>& from) {
  base::ListValue* list = new base::ListValue();
  PopulateListFromArray(from, list);
  return scoped_ptr<base::Value>(list);
}

template <class T>
scoped_ptr<base::Value> CreateValueFromOptionalArray(
    const scoped_ptr<std::vector<T> >& from) {
  if (from.get())
    return CreateValueFromArray(*from);
  return scoped_ptr<base::Value>();
}

std::string ValueTypeToString(base::Value::Type type);

}  // namespace util
}  // namespace json_schema_compiler

#endif // TOOLS_JSON_SCHEMA_COMPILER_UTIL_H__
