/*
 *  GTCommonAPI.cpp
 *  All
 *
 *  Created by nhn on 11. 1. 19..
 *  Copyright 2011 __MyCompanyName__. All rights reserved.
 *
 */
#include "StdAfx.h"
#include "GTCommonAPI.h"
#include <Foundation/Foundation.h>
#include <CoreFoundation/CoreFoundation.h>
#include "GTCommonAPI.h"
#include <fcntl.h>
#if TARGET_OS_IPHONE
#import <UIKit/UIDevice.h>
#import <UIKit/UIScreen.h>
#endif
#import "GTAutoReleasePool.h"
#import <sys/sysctl.h>
#include <sys/stat.h>

static wchar_t g_wszUUID[128];

static bool g_bFirstReadFlag = true;



size_t GTCommonAPI::StrLen(LPCWSTR str)
{
	return str ? wcslen(str) : 0;
}	

const wchar_t * GTCommonAPI::GetUUID(void)
{
	CFUUIDRef uuidObject = CFUUIDCreate(kCFAllocatorDefault);
	CFStringRef uuidStr = CFUUIDCreateString(kCFAllocatorDefault, uuidObject);
	
	swprintf(g_wszUUID, sizeof(g_wszUUID)-1, L"%s", CFStringGetCStringPtr(uuidStr, kCFStringEncodingUTF8));
	
	CFRelease(uuidObject);
	CFRelease(uuidStr);
	
	return g_wszUUID;
}


#if TARGET_OS_IPHONE
void GTCommonAPI::GetDeviceUniqueId(char *result, size_t size)
{
	CGTAutoReleasePool pool;
	NSString *uid = [[UIDevice currentDevice] uniqueIdentifier];
	
	snprintf(result, size-1, "%s", [uid UTF8String]); 
	
}
#endif


void GTCommonAPI::TimeToSystemTime(__time32_t t, LPSYSTEMTIME pst)
{
	struct tm *ptm;
	ptm = _localtime32(&t);
	
	if(!pst)
		return;
	
	pst->wYear = ptm->tm_year + 1900;
	pst->wMonth = ptm->tm_mon + 1;
	pst->wDay = ptm->tm_mday;
	pst->wHour = ptm->tm_hour;
	pst->wMinute = ptm->tm_min;
	pst->wSecond = ptm->tm_sec;
	pst->wMilliseconds = 0;
	pst->wDayOfWeek = ptm->tm_wday;
}


__time32_t GTCommonAPI::SystemTimeToTime(LPSYSTEMTIME pst)
{
	struct tm *ptm;

	__time32_t t = time(NULL);
	ptm = _localtime32(&t);
	
	if(!pst)
		return 0;
	
	ptm->tm_year = pst->wYear - 1900;
	ptm->tm_mon = pst->wMonth - 1;
	ptm->tm_mday = pst->wDay;
	ptm->tm_hour = pst->wHour;
	ptm->tm_min = pst->wMinute;
	ptm->tm_sec = pst->wSecond;
	
	return mktime(ptm);
}


unsigned long long GTCommonAPI::GetFileSize(const char *filename)
{
	CGTAutoReleasePool pool;
	
	NSString *strPath = [NSString stringWithUTF8String:filename];
	
	NSFileManager *fileManager = [NSFileManager defaultManager];

	if (![fileManager fileExistsAtPath:strPath])
		return 0;
	
	NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:strPath error:nil];
	
	if(fileAttributes == nil)
		return 0;
	
	return [fileAttributes fileSize];
}


void GTCommonAPI::WriteTextFile(const char *filename, const char *data)
{
	CGTAutoReleasePool pool;
	
	NSString* docDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
	NSString* path = [NSString stringWithFormat:@"%@/%s.txt", docDirectory, filename];
	
	//NSString* text = [NSString stringWithUTF8String:data];
	//[text writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:NULL];
	
	FILE *fp = fopen([path UTF8String], "a");
	fputs(data, fp);
	fclose(fp);
}


size_t GTCommonAPI::WriteDataFile(const char *filename, const void *data, size_t size)
{
	CGTAutoReleasePool pool;
	
	NSFileManager *fileManager = [NSFileManager defaultManager];
	
	NSString *strFullPath = [NSString stringWithUTF8String:filename];
	
	NSString *strPath = [strFullPath stringByDeletingLastPathComponent];
	
	CreateDirectory([strPath UTF8String]);
		
	FILE *fp = fopen(filename, "w+");
	if(NULL == fp)
		return 0;
	
	size_t ret = fwrite(data, 1, size, fp);
	fclose(fp);
	return ret;
}


bool GTCommonAPI::DeleteFile(const char *src)
{
    if( NULL == src || strlen(src) <= 0)
        return false;

	if(IsDirectory(src))
		return false;
    
	CGTAutoReleasePool pool;
    
	
	NSFileManager *fileManager = [NSFileManager defaultManager];
	
	NSString *strFullPath = [NSString stringWithUTF8String:src];
	
	NSError *err = nil;
	return [fileManager removeItemAtPath:strFullPath error:&err] ? true : false;
}


bool GTCommonAPI::MoveFile(const char *src, const char *dst)
{
	CGTAutoReleasePool pool;
	
	NSFileManager *fileManager = [NSFileManager defaultManager];
	
	//printf("MOVE FILE DEBUG : %s => %s\n", src, dst);
	NSString *strSrc = [NSString stringWithUTF8String:src];
	NSString *strDst = [NSString stringWithUTF8String:dst];
	
	NSError *err = nil;
	return [fileManager moveItemAtPath:strSrc toPath:strDst error:&err] ? true : false;	
}


bool GTCommonAPI::CopyFile(const char *src, const char *dst)
{
	CGTAutoReleasePool pool;
	
	NSFileManager *fileManager = [NSFileManager defaultManager];
	
	NSString *strSrc = [NSString stringWithUTF8String:src];
	NSString *strDst = [NSString stringWithUTF8String:dst];
	
	NSError *err = nil;
    
    DeleteFile(dst);
    
	return [fileManager copyItemAtPath:strSrc toPath:strDst error:&err] ? true : false;
}


bool GTCommonAPI::CreateDirectory(const char *path)
{
	CGTAutoReleasePool pool;
	
	NSFileManager *fileManager = [NSFileManager defaultManager];
	
	NSString *strPath = [NSString stringWithUTF8String:path];
	
	if (![fileManager fileExistsAtPath:strPath])
		return [fileManager createDirectoryAtPath:strPath withIntermediateDirectories:YES attributes:nil error:nil] ? true : false;
	
	return true;
}


char * GTCommonAPI::ReadDataFileAlloc(const char *filename, size_t &resultsize)
{
	resultsize = GetFileSize(filename);
	if(resultsize <= 0)
		return NULL;
	
	char *resultdata = new char[resultsize + 1];
	memset(resultdata, 0, resultsize + 1);
	
	resultsize = ReadDataFile(filename, resultdata, resultsize);
	
	if(resultsize <= 0)
	{
		delete [] resultdata;
		return NULL;
	}
	
	return resultdata;
}


size_t GTCommonAPI::ReadDataFile(const char *filename, char *result, size_t size)
{
	CGTAutoReleasePool pool;
	
	int fd = open(filename, O_RDONLY);
	
	if(-1 == fd)
	{
		return -1;
	}
	
	char buf[2048];
	DWORD dwTotalRead = 0;
	DWORD dwRead;
	DWORD dwFileSize = GTCommonAPI::GetFileSize(filename);
	
	while(dwTotalRead < dwFileSize)
	{
		dwRead = read(fd, buf, sizeof(buf));
		
		assert(dwFileSize >= dwTotalRead + dwRead);
		
		memcpy(result + dwTotalRead, buf, dwRead);
		dwTotalRead += dwRead;
	}
	close(fd);
	
	return dwTotalRead;
}


void GTCommonAPI::GetLocalAppPath(char *result, size_t size)
{
	CGTAutoReleasePool pool;
	
	NSString* docDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
	
	snprintf(result, size-1, "%s", [docDirectory UTF8String]);
}


bool GTCommonAPI::IsDirectory(const char *path)
{
	CGTAutoReleasePool pool;
	
	NSFileManager *fileManager = [NSFileManager defaultManager];
	
	NSString *strPath = [NSString stringWithUTF8String:path];

	BOOL isDir = NO;
	if ([fileManager fileExistsAtPath:strPath isDirectory:&isDir] && isDir) 
	{
		return true;
	}
	
	return false;
}


bool GTCommonAPI::IsFileExist(const char *fileFullPath)
{
    struct stat stFileInfo; 
    bool blnReturn; 
    int intStat; 
    
    // Attempt to get the file attributes 
    if(stat(fileFullPath, &stFileInfo) == 0)
        return true;
    
    return false;
}


static std::string _GetSysInfoByName( const char* typeSpecifier )
{
	size_t size;
	sysctlbyname(typeSpecifier, NULL, &size, NULL, 0);
	char *answer = new char[size];
	sysctlbyname(typeSpecifier, answer, &size, NULL, 0);
	std::string toReturn = answer;
	delete [] answer;
	return toReturn;
}

#if TARGET_OS_IPHONE
std::string GTCommonAPI::GetOsVersion()
{
	NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
	
	NSString* osVersion = [[UIDevice currentDevice] systemVersion];
	std::string toReturn = [osVersion UTF8String];
	
	[pool release];
	
	return toReturn;
}
#endif

/*
 Platforms
 
 iFPGA ->		??
 
 iPhone1,1 ->	iPhone 1G
 iPhone1,2 ->	iPhone 3G
 iPhone2,1 ->	iPhone 3GS
 iPhone3,1 ->	iPhone 4/AT&T
 iPhone3,2 ->	iPhone 4/Other Carrier?
 iPhone3,3 ->	iPhone 4/Other Carrier?
 iPhone4,1 ->	??iPhone 5
 
 iPod1,1   -> iPod touch 1G 
 iPod2,1   -> iPod touch 2G 
 iPod2,2   -> ??iPod touch 2.5G
 iPod3,1   -> iPod touch 3G
 iPod4,1   -> iPod touch 4G
 iPod5,1   -> ??iPod touch 5G
 
 iPad1,1   -> iPad 1G, WiFi
 iPad1,?   -> iPad 1G, 3G <- needs 3G owner to test
 iPad2,1   -> iPad 2G (iProd 2,1)
 
 AppleTV2,1 -> AppleTV 2
 
 i386, x86_64 -> iPhone Simulator
 */
std::string GTCommonAPI::GetDeviceVersion()
{
	return _GetSysInfoByName( "hw.machine" );
}

#if TARGET_OS_IPHONE
bool GTCommonAPI::IsLetinaDisplay()
{
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] && [[UIScreen mainScreen] scale] == 2 ) 
        return true;
    return false;
}
#endif

void GTCommonAPI::PrintLog(const char *log)
{
    NSLog(@"%s", log);
}

static void _RegisterFirstSettingBundleDictionary(void)
{
	NSString *settingsBundle = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"bundle"];
    
    // In Build Run Script, we rename Setting Bundle path name in ReleaseAppStore bulid.
    // Refer to Run Script...
    if ( nil == settingsBundle )
        settingsBundle = [[NSBundle mainBundle] pathForResource:@"Settings_Release" ofType:@"bundle"];
    
	if( nil == settingsBundle) {
		NSLog(@"Could not find Settings.bundle");
        assert(false);
		return;
	}
	
	NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[settingsBundle stringByAppendingPathComponent:@"Root.plist"]];
	NSArray *preferences = [settings objectForKey:@"PreferenceSpecifiers"];
	
	NSMutableDictionary *defaultsToRegister = [[NSMutableDictionary alloc] initWithCapacity:[preferences count]];
	for(NSDictionary *prefSpecification in preferences) {
		NSString *key = [prefSpecification objectForKey:@"Key"];
		if(key) {
			[defaultsToRegister setObject:[prefSpecification objectForKey:@"DefaultValue"] forKey:key];
		}
	}
	[[NSUserDefaults standardUserDefaults] registerDefaults:defaultsToRegister];
	[defaultsToRegister release];
}


int GTCommonAPI::GTSetting::ReadIntSettingBundle(const char *strKeyName)
{
	NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    
	if(g_bFirstReadFlag)
	{
		_RegisterFirstSettingBundleDictionary();
		g_bFirstReadFlag = false;
	}
	
	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
	
	NSString* sKey = [NSString stringWithUTF8String:strKeyName];
	
	NSInteger nValue = [defaults integerForKey:sKey];
	
	[pool release];
	return nValue;
}


std::string GTCommonAPI::GTSetting::ReadStringSettingBundle(const char *strKeyName)
{
	NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
	
	if(g_bFirstReadFlag)
	{
		_RegisterFirstSettingBundleDictionary();
		g_bFirstReadFlag = false;
	}
	
	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
	
	NSString* sKey = [NSString stringWithUTF8String:strKeyName];
	
	NSString* sValue = [defaults stringForKey:sKey];
    
	assert(sValue);
	
	std::string result = [sValue UTF8String];
	
	[pool release];
    
	return result;
}

void GTCommonAPI::GTSetting::SetFloatValue(const char *strKeyName, const float value)
{
    [[NSUserDefaults standardUserDefaults] setFloat:value
                                             forKey:[NSString stringWithUTF8String:strKeyName]];
}

bool GTCommonAPI::GTSetting::GetFloatValue(const char *strKeyName, float *out)
{
    NSString *key = [NSString stringWithUTF8String:strKeyName];
    if ([[NSUserDefaults standardUserDefaults] objectForKey:key] == nil)
        return false;
    
    *out = [[NSUserDefaults standardUserDefaults] floatForKey:key];
    return true;
}


// EOF
