#include "aoflagger.h"
#include "structures.h"

#include "../structures/image2d.h"

#include <stdexcept>

namespace aoflagger {

ImageSet::ImageSet() :
	_data(nullptr)
{ }

ImageSet::ImageSet(size_t width, size_t height, size_t count) :
	_data(new ImageSetData(count))
{
	assertValidCount(count);
	for(size_t i=0; i!=count; ++i)
		_data->images[i] = Image2D::CreateUnsetImagePtr(width, height);
}

ImageSet::ImageSet(size_t width, size_t height, size_t count, float initialValue) :
	_data(new ImageSetData(count))
{
	assertValidCount(count);
	for(size_t i=0; i!=count; ++i)
		_data->images[i] = Image2D::CreateSetImagePtr(width, height, initialValue);
}

ImageSet::ImageSet(size_t width, size_t height, size_t count, size_t widthCapacity) :
	_data(new ImageSetData(count))
{
	assertValidCount(count);
	for(size_t i=0; i!=count; ++i)
		_data->images[i] = Image2D::CreateUnsetImagePtr(width, height, widthCapacity);
}

ImageSet::ImageSet(size_t width, size_t height, size_t count, float initialValue, size_t widthCapacity) :
	_data(new ImageSetData(count))
{
	assertValidCount(count);
	for(size_t i=0; i!=count; ++i)
		_data->images[i] = Image2D::CreateSetImagePtr(width, height, initialValue, widthCapacity);
}

ImageSet::ImageSet(const ImageSet& sourceImageSet) :
	_data(sourceImageSet._data!=nullptr
		? new ImageSetData(*sourceImageSet._data)
		: nullptr)
{
}

ImageSet::ImageSet::ImageSet(aoflagger::ImageSet&& sourceImageSet) :
	_data(std::move(sourceImageSet._data))
{ }

ImageSet::~ImageSet()
{ }

ImageSet &ImageSet::operator=(const ImageSet& sourceImageSet)
{
	if(sourceImageSet._data == nullptr)
	{
		_data.reset();
	}
	else if(_data == nullptr)
	{
		_data.reset(new ImageSetData(*sourceImageSet._data));
	}
	else {
		*_data = *sourceImageSet._data;
	}
	return *this;
}

ImageSet &ImageSet::operator=(ImageSet&& sourceImageSet)
{
	std::swap(_data, sourceImageSet._data);
	return *this;
}

void ImageSet::assertValidCount(size_t count)
{
	if(count != 1 && count != 2 && count != 4 && count != 8)
		throw std::runtime_error("Invalid count specified when creating image set for aoflagger; should be 1, 2, 4 or 8.");
}

float *ImageSet::ImageBuffer(size_t imageIndex)
{
	return _data->images[imageIndex]->Data();
}

const float *ImageSet::ImageBuffer(size_t imageIndex) const
{
	return _data->images[imageIndex]->Data();
}

size_t ImageSet::Width() const
{
	return _data->images[0]->Width();
}

size_t ImageSet::Height() const
{
	return _data->images[0]->Height();
}

size_t ImageSet::ImageCount() const
{
	return _data->images.size();
}

size_t ImageSet::HorizontalStride() const
{
	return _data->images[0]->Stride();
}

void ImageSet::Set(float newValue)
{
	for(std::vector<Image2DPtr>::iterator imgPtr = _data->images.begin(); imgPtr != _data->images.end(); ++imgPtr)
	{
		(*imgPtr)->SetAll(newValue);
	}
}

void ImageSet::ResizeWithoutReallocation(size_t newWidth) const
{
	for(std::vector<Image2DPtr>::iterator imgPtr = _data->images.begin(); imgPtr != _data->images.end(); ++imgPtr)
	{
		(*imgPtr)->ResizeWithoutReallocation(newWidth);
	}
}

}
