#pragma once

#include <vector>
#include "IndexedData.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// This class can be used to store a mapping of vectors between sets of N-dimensional data, to enable convenient 
// reading and writing between mappings
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace gelib_impl
{

	template <const size_t N>
	class IndexedObject
	{
		std::vector<const IndexedData<N>*> m_input_data_ref;
		IndexedData<N>* m_output_data_ref;

	public:
		virtual ~IndexedObject() = default;
		IndexedObject(std::vector<const IndexedData<N>*> const& input, IndexedData<N>* output)
			:
			m_input_data_ref(input),
			m_output_data_ref(output)
		{}

		std::vector<const IndexedData<N>*> const & get_input_data() const
		{
			return m_input_data_ref;
		}

		void write_vector(d_vector& out, size_t dimension)
		{
			IndexedData<N>::insert_vector(out, get_output_start(), m_output_data_ref->get_data_gap(dimension));
		}

		void read_vector(d_vector& in, size_t dimension, size_t which) const
		{
			IndexedData<N>::extract_vector(in, get_input_start(which), m_input_data_ref[which]->get_data_gap(dimension));
		}

		void read_vector(d_vector& in, size_t dimension, size_t which, size_t data_gap) const
		{
			IndexedData<N>::extract_vector(in, get_input_start(which), data_gap);
		}


		virtual std::array<int, N>& get_indices() const = 0;

		virtual const double* get_grid_start() const = 0;

		virtual const double* get_input_start(size_t which) const = 0;

		virtual double* get_output_start() = 0;

		virtual size_t no_grid_points() const = 0;

		virtual size_t get_fixed_depth() const = 0;
	};

}



