//
// Array.h
//
// Library: MongoDB
// Package: MongoDB
// Module:  Array
//
// Definition of the Array class.
//
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier:	BSL-1.0
//


#ifndef MongoDB_Array_INCLUDED
#define MongoDB_Array_INCLUDED


#include "Poco/NumberFormatter.h"
#include "Poco/MongoDB/MongoDB.h"
#include "Poco/MongoDB/Document.h"


namespace Poco {
namespace MongoDB {


class MongoDB_API Array: public Document
	/// This class represents a BSON Array.
{
public:
	using Ptr = SharedPtr<Array>;

	Array();
		/// Creates an empty Array.

	~Array() override;
		/// Destroys the Array.

	// Document template functions available for backward compatibility
	using Document::add;
	using Document::get;

	template<typename T>
	Document& add(T value)
		/// Creates an element with the name from the current pos and value and
		/// adds it to the array document.
		///
		/// The active document is returned to allow chaining of the add methods.
	{
		return Document::add<T>(Poco::NumberFormatter::format(size()), value);
	}

	Document& add(const char* value)
		/// Creates an element with a name from the current pos and value and
		/// adds it to the array document.
		///
		/// The active document is returned to allow chaining of the add methods.
	{
		return Document::add(Poco::NumberFormatter::format(size()), value);
	}

	template<typename T>
	T get(std::size_t pos) const
		/// Returns the element at the given index and tries to convert
		/// it to the template type. If the element is not found, a
		/// Poco::NotFoundException will be thrown. If the element cannot be
		/// converted a BadCastException will be thrown.
	{
		return Document::get<T>(Poco::NumberFormatter::format(pos));
	}

	template<typename T>
	T get(std::size_t pos, const T& deflt) const
		/// Returns the element at the given index and tries to convert
		/// it to the template type. If the element is not found, or
		/// has the wrong type, the deflt argument will be returned.
	{
		return Document::get<T>(Poco::NumberFormatter::format(pos), deflt);
	}

	Element::Ptr get(std::size_t pos) const;
		/// Returns the element at the given index.
		/// An empty element will be returned if the element is not found.

	template<typename T>
	bool isType(std::size_t pos) const
		/// Returns true if the type of the element equals the TypeId of ElementTrait,
		/// otherwise false.
	{
		return Document::isType<T>(Poco::NumberFormatter::format(pos));
	}

	std::string toString(int indent = 0) const override;
		/// Returns a string representation of the Array.

private:
	friend void BSONReader::read<Array::Ptr>(Array::Ptr& to);
};


// BSON Embedded Array
// spec: document
template<>
struct ElementTraits<Array::Ptr>
{
	enum { TypeId = 0x04 };

	static std::string toString(const Array::Ptr& value, int indent = 0)
	{
		//TODO:
		return value.isNull() ? "null" : value->toString(indent);
	}
};


template<>
inline void BSONReader::read<Array::Ptr>(Array::Ptr& to)
{
	to->read(_reader);
}


template<>
inline void BSONWriter::write<Array::Ptr>(Array::Ptr& from)
{
	from->write(_writer);
}


} } // namespace Poco::MongoDB


#endif // MongoDB_Array_INCLUDED
