#include "pch.h"
#include "twitchsdk/chat/ichatchannel.h"
#include "ChatImpl.h"
#include "ChannelImpl.h"

using namespace TwitchInGames;

void ChannelImpl::ChatChannelListener::ChatChannelStateChanged(ttv::UserId /*userId*/, ttv::ChannelId /*channelId*/, ttv::chat::ChatChannelState /*state*/, TTV_ErrorCode /*ec*/) {}

void ChannelImpl::ChatChannelListener::ChatChannelInfoChanged(ttv::UserId /*userId*/, ttv::ChannelId /*channelId*/, ttv::chat::ChatChannelInfo const& /*channelInfo*/) {}

void ChannelImpl::ChatChannelListener::ChatChannelRestrictionsChanged(ttv::UserId /*userId*/, ttv::ChannelId /*channelId*/, ttv::chat::ChatChannelRestrictions const& /*restrictions*/) {}

void ChannelImpl::ChatChannelListener::ChatChannelLocalUserChanged(ttv::UserId /*userId*/, ttv::ChannelId /*channelId*/, ttv::chat::ChatUserInfo const& /*userInfo*/) {}

void ChannelImpl::ChatChannelListener::ChatChannelMessagesReceived(ttv::UserId /*userId*/, ttv::ChannelId /*channelId*/, std::vector<ttv::chat::LiveChatMessage> const& messageList) {
	for(auto& message : messageList) {
		if(message.messageInfo.displayName.empty()) {
			continue;
		}
		std::string s;
		for(auto const& token : message.messageInfo.tokens) {
			if(token->GetType() == ttv::chat::MessageToken::Type::Text) {
				auto const& textToken = *static_cast<ttv::chat::TextToken const*>(token.get());
				s += textToken.text;
				s += ' ';
			}
		}
		s.pop_back();
		receiveCallback(channel, ToTstring(message.messageInfo.userName), ToTstring(s));
	}
}

void ChannelImpl::ChatChannelListener::ChatChannelSubscriptionNoticeReceived(ttv::UserId /*userId*/, ttv::ChannelId /*channelId*/, ttv::chat::SubscriptionNotice const& /*notice*/) {}

void ChannelImpl::ChatChannelListener::ChatChannelFirstTimeChatterNoticeReceived(ttv::UserId /*userId*/, ttv::ChannelId /*channelId*/, ttv::chat::FirstTimeChatterNotice const& /*notice*/) {}

void ChannelImpl::ChatChannelListener::ChatChannelRaidNoticeReceived(ttv::UserId /*userId*/, ttv::ChannelId /*channelId*/, ttv::chat::RaidNotice const& /*notice*/) {}

void ChannelImpl::ChatChannelListener::ChatChannelUnraidNoticeReceived(ttv::UserId /*userId*/, ttv::ChannelId /*channelId*/, ttv::chat::UnraidNotice const& /*notice*/) {}

void ChannelImpl::ChatChannelListener::ChatChannelMessagesCleared(ttv::UserId /*userId*/, ttv::ChannelId /*channelId*/) {}

void ChannelImpl::ChatChannelListener::ChatChannelUserMessagesCleared(ttv::UserId /*userId*/, ttv::ChannelId /*channelId*/, ttv::UserId /*clearUserId*/) {}

void ChannelImpl::ChatChannelListener::ChatChannelHostTargetChanged(ttv::UserId /*userId*/, ttv::ChannelId /*channelId*/, std::string const& /*targetChannelName*/, uint32_t /*numViewers*/) {}

void ChannelImpl::ChatChannelListener::ChatChannelNoticeReceived(ttv::UserId /*userId*/, ttv::ChannelId /*channelId*/, std::string const& /*noticeId*/, std::map<std::string, std::string> const& /*params*/) {}

ChannelImpl::ChannelImpl(Chat::Channel& channel, ChatImpl& chatImpl, ttv::ChannelId channelId, Chat::Channel::ReceiveCallback receiveCallback) :
	chatChannelListener(std::make_shared<ChatChannelListener>(channel, receiveCallback)) {
	if(channelId == 0) {
		DebugWriteLine(_T("[ChannelImpl::ChannelImpl] Invalid channel identifier"));
		throw TwitchException(FromPlatformError(ERROR_BAD_ARGUMENTS));
	}
	chatChannel = chatImpl.CreateChannel(channelId, chatChannelListener);
	chatChannel->Connect();
}

TwitchInGames::ChannelImpl::~ChannelImpl() {
	try {
		chatChannel->Disconnect();
	} catch(std::exception const& ex) {
		UNREFERENCED_PARAMETER(ex);
		DebugWriteLine(_T("warning: Disconnect failed: %s"), ToTstring(ex.what()).c_str());
		// Ignore exceptions.
	} catch(...) {
		DebugWriteLine(_T("warning: Disconnect failed"));
		// Ignore exceptions.
	}
}

std::future<void> TwitchInGames::ChannelImpl::Send(string_t message) {
	std::promise<void> sendPromise;
	sendPromise.set_value();
	chatChannel->SendMessage(FromTstring(message));
	return sendPromise.get_future();
}
