#include "NovaStdAfx.h"
#include "Common.h"
#include <iostream>
#include <sstream>

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

#ifdef NOVA_GUI
HANDLE gameStateMutex;
#endif

std::ofstream fileLog;

InformationManager* informationManager;
WorkerManager* workerManager;
SquadManager* squadManager;
BuildManager* buildManager;

bool ONLY_MICRO;
bool HIGH_LEVEL_SEARCH = false;
bool PRINT_BUILD_ORDER = false;
bool PRINT_AIR_DPS = false;
bool PRINT_GROUND_DPS = false;
bool PRINT_PRODUCTION = false;
bool PRINT_BUILD_MAP = false;
bool PRINT_REGION_ID_MAP = false;
bool PRINT_SIEGE_MAP = false;

bool usingCloackUnits = false;
int totalKitingFrames = 0;
bool kitingFrame;

HighLevelStats_t stats;

BWAPI::Position rotatePosition(int degree, BWAPI::Position position, BWAPI::Position origen)
{
	//BWAPI::Positon finalPosition;
	double radians = degree * M_PI / 180;
	// substract origin
	int xT1 = position.x() - origen.x();
	int yT1 = position.y() - origen.y();
	// rotate
	int xRotated = (int)( (xT1*cos(radians)) - (yT1*sin(radians)) );
	int yRotated = (int)( (yT1*cos(radians)) - (xT1*sin(radians)) );
	// back to origin
	int xT2 = xRotated + origen.x();
	int yT2 = yRotated + origen.y();
	return BWAPI::Position(xT2, yT2);
}

BWAPI::Position getPositionInDirection(BWAPI::Position origen, BWAPI::Position direction, int distance)
{
	// get the angle of the direction
// 	double angle = atan2((double)(direction.y() - origen.y()), (double)(direction.x() - origen.x()));
// 	// move the point with the given distance and direction
// 	int newX = (int)(origen.x() + cos(angle) * distance);
// 	int newY = (int)(origen.y() + sin(angle) * distance);

	// get unitary vector on right direction
	double dx = (double)(direction.x() - origen.x());
	double dy = (double)(direction.y() - origen.y());
	double norma = sqrt(dx*dx+dy*dy);
	dx /= norma;
	dy /= norma;
	// scale vector with "distance" and add to origin:
	int newX = (int)(origen.x() + dx * distance);
	int newY = (int)(origen.y() + dy * distance);

	return BWAPI::Position(newX, newY);
}

std::vector<std::string> &splitString(const std::string &s, char delim, std::vector<std::string> &elems) {
    std::stringstream ss(s);
    std::string item;
    while(std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}


std::vector<std::string> splitString(const std::string &s, char delim) {
    std::vector<std::string> elems;
    splitString(s, delim, elems);
	return elems;
}

std::string intToString(const int& number)
{
	std::ostringstream oss;
	oss << number;
	return oss.str();
}

//----------------------------- LOAD CONFIG FXNS ------------------------------------------
std::string configPath;
std::string LoadConfigString(const char *pszKey, const char *pszItem, const char *pszDefault)
{
    char buffer[MAX_PATH];
    GetPrivateProfileString(pszKey, pszItem, pszDefault ? pszDefault : "", buffer, MAX_PATH, configPath.c_str());
    return std::string(buffer);
}
int LoadConfigInt(const char *pszKey, const char *pszItem, const int iDefault)
{
    return GetPrivateProfileInt(pszKey, pszItem, iDefault, configPath.c_str());
}
