/**********************************************************************
 * LeechCraft - modular cross-platform feature rich internet client.
 * Copyright (C) 2006-2014  Georg Rudoy
 *
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
 **********************************************************************/

#pragma once

#include <memory>
#include <QObject>
#include <util/sll/either.h>
#include <util/sll/void.h>
#include <util/threads/coro/taskfwd.h>
#include <interfaces/azoth/iaccount.h>
#include <interfaces/azoth/isupportmediacalls.h>
#include "toxaccountconfiguration.h"
#include "types.h"

namespace LC::Azoth::Sarin
{
	class ToxProtocol;
	class ToxRunner;
	class ToxContact;
	class ChatMessage;
	class MessagesManager;
	class AccountConfigDialog;
	class FileTransferManager;
	class ConfsManager;
	class GroupsManager;

	class ToxAccount : public QObject
					 , public IAccount
					 , public ISupportMediaCalls
	{
		Q_OBJECT
		Q_INTERFACES (LC::Azoth::IAccount LC::Azoth::ISupportMediaCalls)

		ToxProtocol * const Proto_;
		const QByteArray UID_;

		QString Name_;
		QString Nick_;

		ToxAccountConfiguration ToxConfig_;

		QByteArray ToxState_;

		QAction * const ActionGetToxId_;

		std::shared_ptr<ToxRunner> Tox_;
		EntryStatus Status_;

		MessagesManager * const MsgsMgr_;
		FileTransferManager * const XferMgr_;

		ConfsManager * const ConfsMgr_;
		GroupsManager * const GroupsMgr_;

		QHash<Pubkey, ToxContact*> Contacts_;

		ToxAccount (const QByteArray&, const QString& name, ToxProtocol*);
	public:
		ToxAccount (const QString& name, ToxProtocol*);

		QByteArray Serialize ();
		static ToxAccount* Deserialize (const QByteArray&, ToxProtocol*);

		void SetNickname (const QString&);

		ToxContact* GetByAzothId (const QString&) const;
		ToxContact* GetByPubkey (Pubkey) const;
		ToxContact& GetOrCreateByPubkey (Pubkey);

		std::shared_ptr<ToxRunner> GetTox ();

		QObject* GetQObject () override;
		QObject* GetParentProtocol () const override;
		AccountFeatures GetAccountFeatures () const override;

		QList<QObject*> GetCLEntries () override;

		QString GetAccountName () const override;
		QString GetOurNick () const override;
		void RenameAccount (const QString& name) override;
		QByteArray GetAccountID () const override;

		QList<QAction*> GetActions () const override;
		void OpenConfigurationDialog () override;
		EntryStatus GetState () const override;
		void ChangeState (const EntryStatus&) override;

		void Authorize (QObject*) override;
		void DenyAuth (QObject*) override;
		void RequestAuth (const QString&, const QString&, const QString&, const QStringList&) override;
		void RemoveEntry (QObject*) override;

		MediaCallFeatures GetMediaCallFeatures () const override;
		QObject* Call (const QString& id, const QString& variant) override;

		QObject* GetTransferManager () const override;

		void SendMessage (Pubkey pkey, ChatMessage *msg);
		Util::ContextTask<void> SetTypingState (Pubkey pkey, bool isTyping);

		ConfsManager& GetConfsManager ();
		GroupsManager& GetGroupsManager ();
	private:
		Util::ContextTask<void> RunRequestAuth (Pubkey, QString);
		Util::ContextTask<void> RunRemoveEntry (ToxContact*);

		Util::ContextTask<void> InitThread (EntryStatus);
		Util::ContextTask<void> LoadFriends ();
		void ConnectSignalsPreRun ();

		void InitEntry (Pubkey);
		void InitEntries (const QList<Pubkey>&);

		void HandleConfigAccepted (AccountConfigDialog*);

		void HandleIncomingCall (Pubkey, int32_t);

		Util::ContextTask<void> HandleToxIdRequested ();

		void HandleGotFriendRequest (Pubkey, const QString&);
		void HandleRemovedFriend (Pubkey);

		void HandleFriendNameChanged (Pubkey, const QString&);
		void HandleFriendStatusChanged (Pubkey, const EntryStatus&);
		void HandleFriendTypingChanged (Pubkey, bool);
	signals:
		void accountRenamed (const QString&) override;
		void authorizationRequested (QObject*, const QString&) override;
		void gotCLItems (const QList<QObject*>&) override;
		void itemCancelledSubscription (QObject*, const QString&) override;
		void itemGrantedSubscription (QObject*, const QString&) override;
		void itemSubscribed (QObject*, const QString&) override;
		void itemUnsubscribed (const QString& entryID, const QString&) override;
		void itemUnsubscribed (QObject*, const QString&) override;
		void mucInvitationReceived (const QVariantMap&, const QString&, const QString&) override;
		void removedCLItems (const QList< QObject* >&) override;
		void statusChanged (const EntryStatus&) override;

		void accountChanged (ToxAccount*);

		void threadChanged (const std::shared_ptr<ToxRunner>&);

		void called (QObject*) override;
	};
}
