#include "itemstore.h"
#include <QJsonArray>
#include <typeinfo>

ItemStore::ItemStore(QObject *parent): QObject(parent)
{
}

void ItemStore::addItem(const ItemAddRequest& item)
{
	qDebug()<<"Item add request for"<<item.payload->getName()<<item.payload->id();
	std::shared_ptr<Item> matched = nullptr;
	for(unsigned i = 0; i < items_.size(); i++ )
	{
		if(*items_[i] == *item.payload)
		{
			matched = items_[i];
			assert(matched->id() == items_[i]->id());
			break;
		}
	}
	if(!matched)
	{
		items_.push_back(item.payload);
		connect(item.payload.get(), &Item::updated, this, &ItemStore::itemUpdateSlot);
		qDebug()<<"Item"<<item.payload->getName()<<"added"<<(item.payload->getLoaded() ? "from loaded" : "");
		itemAdded(std::weak_ptr<Item>(items_.back()));
	}
	else if(!item.changes.isNone())
	{
		qDebug()<<"Item"<<item.payload->getName()<<"was matched with"<<matched->getName()<<"and has changes";
		ItemUpdateRequest request = item.updateRequest();
		updateItem(request);
	}
}

void ItemStore::addItems(const std::vector<ItemAddRequest>& itemIn)
{
	for(unsigned j = 0; j < itemIn.size(); j++)
		addItem(itemIn[j]);
}

void ItemStore::removeItem(const ItemData& item)
{
	for(unsigned j = 0; j < items_.size(); j++)
	{
		if(item == *items_[j])
		{
			qDebug()<<"Item"<<item.getName()<<"deleted";
			itemDeleted(*items_[j]);
			items_.erase(items_.begin()+j);
			--j;
		}
	}
}

void ItemStore::replaceItems(const std::vector<std::shared_ptr<Item>>& items)
{
	for(const std::shared_ptr<Item>& item : items)
	{
		ItemAddRequest request;
		request.changes = ItemFieldChanges(true);
		request.changes.actors = true;
		request.type = ITEM_UPDATE_LOADED;
		request.payload = item;
		addItem(request);
	}
	std::vector<ItemData> deletedItems;
	for(std::shared_ptr<Item> item : items_)
	{
		if(std::find_if(items.begin(), items.end(), [item](const std::shared_ptr<Item> other){return *item == *other;}) == items.end())
			deletedItems.push_back(*item);
	}
	for(const ItemData& item : deletedItems)
		removeItem(item);
}

void ItemStore::clear()
{
	for(size_t i = 0; i < items_.size(); ++i) itemDeleted(*items_[i]);
	items_.clear();
}

void ItemStore::updateItems(const std::vector<ItemUpdateRequest>& updates)
{
	for(const ItemUpdateRequest& update : updates)
		updateItem(update);
}

void ItemStore::updateItem(const ItemUpdateRequest& update)
{
	for(unsigned i = 0; i < items_.size(); i++ )
	{
		if(items_[i]->operator==(update.payload))
		{
			items_[i]->requestUpdate(update);
			itemUpdated(update);
		}
	}
}

void ItemStore::store(QJsonObject& json)
{
	QJsonArray itemsArray;
	for(size_t i = 0; i < items_.size(); ++i)
	{
		QJsonObject itemObject;
		items_[i]->store(itemObject);
		itemsArray.append(itemObject);
	}
	json["Items"] = itemsArray;
}

void ItemStore::itemUpdateSlot(ItemUpdateRequest update)
{
	itemUpdated(update);
}

std::shared_ptr<Item> ItemStore::getItem(uint32_t id)
{
	for(std::shared_ptr<Item>& item : items_)
	{
		if(item->id() == id)
			return item;
	}
	return nullptr;
}

void ItemStore::registerItemSource(ItemSource* source)
{
	qDebug()<<__func__<<typeid(*source).name();
	connect(source, &ItemSource::gotItems, this, &ItemStore::addItems);
	connect(source, &ItemSource::updateItems, this, &ItemStore::updateItems);
	connect(source, &ItemSource::requestReplaceItems, this, &ItemStore::replaceItems);
	connect(this, &ItemStore::sigRefresh, source, &ItemSource::refresh);
}

void ItemStore::refresh()
{
	for(std::shared_ptr<Item>& item : items_)
		itemDeleted(*item);
	items_.clear();
	sigRefresh();
}

ItemStore globalItems;

