#include <psemek/audio/combine/concat.hpp>

#include <atomic>

namespace psemek::audio
{

	namespace
	{

		struct concat_impl
			: stream
		{
			concat_impl(std::vector<stream_ptr> streams)
				: streams_(std::move(streams))
			{
				length_ = 0;
				for (auto const & stream : streams_)
				{
					if (auto length = stream->length())
						*length_ += *length;
					else
					{
						length_ = std::nullopt;
						break;
					}
				}
			}

			std::optional<std::size_t> length() const override
			{
				return length_;
			}

			std::size_t read(util::span<float> samples) override
			{
				std::size_t count = 0;

				for (; index_ != streams_.size(); ++index_)
				{
					auto read = streams_[index_]->read(samples);
					count += read;
					samples.consume(read);
					if (samples.empty())
						break;
				}

				played_.fetch_add(count);

				return count;
			}

			std::size_t played() const override
			{
				return played_;
			}

		private:
			std::vector<stream_ptr> streams_;
			std::optional<std::size_t> length_;
			std::atomic<std::size_t> played_{0};
			std::size_t index_{0};
		};

	}

	stream_ptr concat(std::vector<stream_ptr> streams)
	{
		return std::make_shared<concat_impl>(std::move(streams));
	}

}
