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

#include <vector>

namespace psemek::audio
{

	namespace
	{

		struct stereo_impl
			: stream
		{
			stereo_impl(stream_ptr left, stream_ptr right)
				: left_(std::move(left))
				, right_(std::move(right))
			{}

			std::optional<std::size_t> length() const override
			{
				auto left = left_->length();
				auto right = right_->length();

				if (left && right)
					return std::min(*left, *right);
				else if (left)
					return left;
				else
					return right;
			}

			std::size_t played() const override
			{
				return std::min(left_->played(), right_->played());
			}

			std::size_t read(util::span<float> samples) override
			{
				if (buffer_.size() < samples.size())
					buffer_.resize(samples.size());

				auto right_result = right_->read(samples);
				auto left_result = left_->read({buffer_.data(), samples.size()});

				auto result = std::min(right_result, left_result);

				{
					auto begin = buffer_.data();
					auto end = buffer_.data() + result;
					auto dst = samples.data();
					for (; begin < end; begin += 2, dst += 2)
						*dst = *begin;
				}
				return result;
			}

		private:
			stream_ptr left_, right_;
			std::vector<float> buffer_;
		};

	}

	stream_ptr stereo(stream_ptr left, stream_ptr right)
	{
		return std::make_shared<stereo_impl>(std::move(left), std::move(right));
	}

}
