//
// pch.h
// Header for standard system include files.
//

#pragma once

#ifdef __ORBIS__
# include <sceerror.h>
# include <net.h>
# include <libsysmodule.h>

# include <atomic>
# include <future>
# include <iostream>
# include <map>
# include <sstream>
# include <string>
# include <typeinfo>
# include <vector>

# define FromPlatformError(error) static_cast<int>(SCE_ERROR_MAKE_ERROR(0, error))
# define UNREFERENCED_PARAMETER(p) ((void)p)
# define _T(s) (s)

using TCHAR= char;
using LPTSTR= TCHAR*;
using LPCTSTR= TCHAR const*;

# define ERROR_SUCCESS 0
# define ERROR_BAD_ARGUMENTS EINVAL
# define ERROR_CONNECTION_INVALID SCE_NET_ENOTCONN
# define ERROR_INVALID_FUNCTION ENOSYS
# define ERROR_INVALID_OPERATION EOPNOTSUPP

# define TEST(caseName,testName) void caseName::testName()
# define EXPECT_TRUE(expr) do { bool result_= PrintResult((expr) ? nullptr : #expr); if(!result_) return; } while(false)
# define EXPECT_FALSE(expr) do { bool result_= PrintResult((expr) ? "!" #expr : nullptr); if(!result_) return; } while(false)
# define EXPECT_EQ(actual,expected) do { auto actual_= (actual); auto expected_= (expected); bool result_= PerformTest(actual_, expected_, [&actual_, &expected_] { return actual_ == expected_; }, "=="); if(!result_) return; } while(false)
# define EXPECT_GE(actual,expected) do { auto actual_= (actual); auto expected_= (expected); bool result_= PerformTest(actual_, expected_, [&actual_, &expected_] { return actual_ >= expected_; }, ">="); if(!result_) return; } while(false)
# define EXPECT_LE(actual,expected) do { auto actual_= (actual); auto expected_= (expected); bool result_= PerformTest(actual_, expected_, [&actual_, &expected_] { return actual_ <= expected_; }, "<="); if(!result_) return; } while(false)
# define EXPECT_NE(actual,expected) do { auto actual_= (actual); auto expected_= (expected); bool result_= PerformTest(actual_, expected_, [&actual_, &expected_] { return actual_ != expected_; }, "!="); if(!result_) return; } while(false)
# define EXPECT_STREQ(actual,expected) do { auto actual_= (actual); auto expected_= (expected); bool result_= PerformTest(actual_, expected_, [&actual_, &expected_] { return strcmp(actual_, expected_) == 0; }, "=="); if(!result_) return; } while(false)
# define EXPECT_ANY_THROW(statement) do { try { statement; PrintResult(#statement " did not throw"); } catch(...) { PrintResult(nullptr); } } while(false)

# include "TwitchInGames.h"

std::ostream& operator<<(std::ostream& os, TwitchInGames::Stream::StreamType type);

extern char const* testName;

inline bool PrintResult(char const* s) {
	std::cout << "TEST CASE " << testName << ' ';
	if(s == nullptr) {
		std::cout << "SUCCEEDED";
	} else {
		std::cout << "FAILED: " << s;
	}
	std::cout << std::endl;
	return s == nullptr;
}

template<typename T, typename U, typename FN>
inline bool PerformTest(T const& actual, U const& expected, FN fn, char const* s) {
	if(fn()) {
		return PrintResult(nullptr);
	}
	std::stringstream ss;
	ss << std::endl << "expected: " << expected << std::endl << s << std::endl << "  actual: " << actual;
	return PrintResult(ss.str().c_str());
}
#else
# define NOMINMAX
# include <WinSock2.h>
# include <WS2tcpip.h>
# include <tchar.h>
# include <ppltasks.h>
# include <future>
# include "gtest/gtest.h"

# define FromPlatformError HRESULT_FROM_WIN32
#endif
#include <stdio.h>
#include <fstream>
#include <unordered_set>
#include <vector>
#include <map>
#include <utility>

#ifdef _UNICODE
using tistream= std::wistream;
using tistringstream= std::wistringstream;
using tofstream= std::wofstream;
using tostream= std::wostream;
using tostringstream= std::wostringstream;
using tstringstream= std::wstringstream;
#else
using tistream= std::istream;
using tistringstream= std::istringstream;
using tofstream= std::ofstream;
using tostream= std::ostream;
using tostringstream= std::ostringstream;
using tstringstream= std::stringstream;
#endif
