/**********************************************************************
 * LeechCraft - modular cross-platform feature rich internet client.
 * Copyright (C) 2006-2014  Georg Rudoy
 *
 * Boost Software License - Version 1.0 - August 17th, 2003
 *
 * Permission is hereby granted, free of charge, to any person or organization
 * obtaining a copy of the software and accompanying documentation covered by
 * this license (the "Software") to use, reproduce, display, distribute,
 * execute, and transmit the Software, and to prepare derivative works of the
 * Software, and to permit third-parties to whom the Software is furnished to
 * do so, all subject to the following:
 *
 * The copyright notices in the Software and this entire statement, including
 * the above license grant, this restriction and the following disclaimer,
 * must be included in all copies of the Software, in whole or in part, and
 * all derivative works of the Software, unless such copies or derivative
 * works are solely in the form of machine-executable object code generated by
 * a source language processor.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 **********************************************************************/

#include "customstatusesmanager.h"
#include <QStandardItemModel>
#include <QCoreApplication>
#include <xmlsettingsdialog/datasourceroles.h>
#include <util/util.h>
#include "interfaces/azoth/azothcommon.h"
#include "core.h"
#include "proxyobject.h"
#include "xmlsettingsmanager.h"
#include "resourcesmanager.h"

namespace LeechCraft
{
namespace Azoth
{
	CustomStatusesManager::CustomStatusesManager (QObject *parent)
	: QObject (parent)
	, Model_ (new QStandardItemModel (this))
	{
		Model_->setColumnCount (3);

		Model_->setHorizontalHeaderLabels ({tr ("Name"), tr ("Status"), tr ("Text") });

		Model_->horizontalHeaderItem (0)->setData (DataSources::DataFieldType::String,
				DataSources::DataSourceRole::FieldType);
		Model_->horizontalHeaderItem (1)->setData (DataSources::DataFieldType::Enum,
				DataSources::DataSourceRole::FieldType);
		QVariantList values;
		auto append = [&values] (State state)
		{
			values << Util::MakeMap<QString, QVariant> ({
					{ "Name", ProxyObject ().StateToString (state) },
					{ "Icon", ResourcesManager::Instance ().GetIconForState (state) },
					{ "ID", QVariant::fromValue (state) }
				});
		};
		append (State::SOnline);
		append (State::SAway);
		append (State::SXA);
		append (State::SDND);
		append (State::SChat);
		append (State::SOffline);
		Model_->horizontalHeaderItem (1)->setData (values, DataSources::DataSourceRole::FieldValues);

		Model_->horizontalHeaderItem (2)->setData (DataSources::DataFieldType::String,
				DataSources::DataSourceRole::FieldType);

		Load ();
	}

	QAbstractItemModel* CustomStatusesManager::GetModel () const
	{
		return Model_;
	}

	QList<CustomStatusesManager::CustomState> CustomStatusesManager::GetStates () const
	{
		QList<CustomState> result;
		for (int i = 0; i < Model_->rowCount (); ++i)
			result << GetCustom (i);
		return result;
	}

	void CustomStatusesManager::Save ()
	{
		QSettings settings (QCoreApplication::organizationName (),
				QCoreApplication::applicationName () + "_Azoth");
		settings.beginGroup ("CustomStatuses");
		settings.beginWriteArray ("Statuses");
		for (int i = 0; i < Model_->rowCount (); ++i)
		{
			settings.setArrayIndex (i);
			const auto& state = GetCustom (i);
			settings.setValue ("Name", state.Name_);
			settings.setValue ("State", static_cast<int> (state.State_));
			settings.setValue ("Text", state.Text_);
		}
		settings.endArray ();
		settings.endGroup ();
	}

	void CustomStatusesManager::Load ()
	{
		QSettings settings (QCoreApplication::organizationName (),
				QCoreApplication::applicationName () + "_Azoth");
		settings.beginGroup ("CustomStatuses");
		for (int i = 0, size = settings.beginReadArray ("Statuses"); i < size; ++i)
		{
			settings.setArrayIndex (i);
			const auto& name = settings.value ("Name").toString ();
			const auto state = static_cast<State> (settings.value ("State").toInt ());
			const auto& text = settings.value ("Text").toString ();

			Add ({ name, state, text });
		}
		settings.endArray ();
		settings.endGroup ();
	}

	void CustomStatusesManager::Add (const CustomState& state, int after)
	{
		ProxyObject proxy;

		QList<QStandardItem*> row;
		row << new QStandardItem (state.Name_);
		row << new QStandardItem (ResourcesManager::Instance ().GetIconForState (state.State_),
				proxy.StateToString (state.State_));
		row << new QStandardItem (state.Text_);
		row.at (1)->setData (static_cast<int> (state.State_));

		if (after == -1)
			Model_->appendRow (row);
		else
			Model_->insertRow (after, row);
	}

	CustomStatusesManager::CustomState CustomStatusesManager::GetCustom (int i) const
	{
		return
		{
			Model_->item (i, 0)->text (),
			static_cast<State> (Model_->item (i, 1)->data ().toInt ()),
			Model_->item (i, 2)->text (),
		};
	}

	namespace
	{
		CustomStatusesManager::CustomState GetState (const QVariantList& vars)
		{
			return
			{
				vars.at (0).toString (),
				vars.at (1).value<State> (),
				vars.at (2).toString ()
			};
		}
	}

	void CustomStatusesManager::addRequested (const QString&, const QVariantList& vars)
	{
		if (vars.size () != Model_->columnCount ())
		{
			qWarning () << Q_FUNC_INFO
					<< "invalid vars";
			return;
		}

		Add (GetState (vars));
		Save ();
	}

	void CustomStatusesManager::modifyRequested (const QString&, int row, const QVariantList& vars)
	{
		if (vars.size () != Model_->columnCount ())
		{
			qWarning () << Q_FUNC_INFO
					<< "invalid vars";
			return;
		}

		Model_->removeRow (row);
		Add (GetState (vars), row);
		Save ();
	}

	void CustomStatusesManager::removeRequested (const QString&, const QModelIndexList& indexes)
	{
		QList<int> rows;
		for (const auto& index : indexes)
			rows << index.row ();

		std::sort (rows.begin (), rows.end (), [] (int l, int r) { return r < l; });

		for (int row : rows)
			Model_->removeRow (row);

		Save ();
	}
}
}
