#include "pch.h"
#include "http/HttpRequest.h"
#include "twitchsdk/core/json/reader.h"
#include "Internal.h"

using namespace ttv;
using namespace TwitchInGames;

namespace {
	tstring const helixStreamsRootUrl = _T("https://api.twitch.tv/helix/streams?");
}

std::future<StreamsResponse> StreamsRequest::Fetch(tstring const& clientId, tstring const& token) {
	auto fn = [this, clientId, token] {
		std::map<tstring, tstring> properties;
		tstring url = helixStreamsRootUrl;
		if(Count != 0) {
			url += _T("&first=") + to_tstring(Count);
		}
		if(Direction != PaginationDirection::None && !Cursor.empty()) {
			url += Direction == PaginationDirection::Forward ? _T("&after=") : _T("&before=");
			url += Cursor;
		}
		if(!CommunityId.empty()) {
			url += _T("&community_id=") + CommunityId;
			properties.insert({ _T("community_id"), CommunityId });
		}
		if(!GameId.empty()) {
			url += _T("&game_id=") + GameId;
			properties.insert({ _T("game_id"), GameId });
		}
		if(!Language.empty()) {
			url += _T("&language=") + Language;
			properties.insert({ _T("language"), Language });
		}
		if(!UserId.empty()) {
			url += _T("&user_id=") + UserId;
			properties.insert({ _T("user_id"), UserId });
		}
		if(!UserLogin.empty()) {
			auto login= ToLowerCase(UserLogin);
			url += _T("&user_login=") + login;
			properties.insert({ _T("user_login"), login });
		}
		auto httpResponse = HttpRequest(clientId, token).Get(url);
		ThrowIfResponseFailed(httpResponse);

		// Parse the response as JSON.
		json::Value jsonVal;
		json::Reader jsonReader;
		auto const& response = httpResponse.Response;
		bool parseSucceeded = jsonReader.parse(response.data(), response.data() + response.size(), jsonVal);
		if(!parseSucceeded) {
			DebugWriteLine(_T("[StreamsRequest::Fetch] JSON parsing failed"));
			throw TwitchException(FromPlatformError(ERROR_INVALID_RESPONSE));
		}

		// Send a science event.
		SendTokenScienceEvent(clientId, token, _T("sdk_stream_get"), properties);

		// Get references for all of the fields.
		StreamsResponse streamsResponse;
		streamsResponse.Cursor = ToTstring(jsonVal["pagination"]["cursor"].asString());
		auto const& data = jsonVal["data"];
		for(auto const& stream : data) {
			auto const& communityIds = stream["community_ids"];
			std::vector<tstring> communityIdsV;
			for(auto const& communityId : communityIds) {
				communityIdsV.emplace_back(ToTstring(communityId.asString()));
			}
			Stream::StreamType type = Stream::StreamType::None;
			if(stream["type"].asString() == "live") {
				type = Stream::StreamType::Live;
			} else if(stream["type"].asString() == "vodcast") {
				type = Stream::StreamType::Vodcast;
			}
			streamsResponse.Streams.emplace_back(Stream{
				communityIdsV,
				ToTstring(stream["game_id"].asString()),
				ToTstring(stream["id"].asString()),
				ToTstring(stream["language"].asString()),
				ParseTime(stream["started_at"].asString()),
				ToTstring(stream["thumbnail_url"].asString()),
				ToTstring(stream["title"].asString()),
				type,
				ToTstring(stream["user_id"].asString()),
				static_cast<unsigned>(stream["viewer_count"].asUInt())
				});
		}
		return streamsResponse;
	};
	return std::async(std::launch::deferred, fn);
}
