//
//  AppDelegate.m
//  ConnectClient
//
//  Created by yjx0755 on 13-11-19.
//  Copyright (c) 2013年 Peergine. All rights reserved.
//

#import "AppDelegate.h"

#import "ViewController.h"
#include "pgLibConnect.h"

static void dprintf0(const char* lpszFmt, ...)
{
	va_list args;
	char szBuf[1024] = {0};
	va_start(args, lpszFmt);
	int iSize = vsnprintf(szBuf, sizeof(szBuf), lpszFmt, args);
	if (iSize > 0 && (iSize + 3) < sizeof(szBuf)) {
		szBuf[iSize] = '\n';
		szBuf[iSize + 1] = '\0';
	    printf("%s", szBuf);
	}
}


void DebugOut(unsigned int uLevel, const char* lpszOut)
{
    dprintf0(lpszOut);
}


static AppDelegate* s_pAppDelegate = nil;

void onCallback(const char* lpszParam)
{
	if (s_pAppDelegate != nil) {
		NSString *sParam = [NSString stringWithUTF8String:lpszParam]; 
		[s_pAppDelegate performSelectorOnMainThread:@selector(cnntCallback:) withObject:sParam waitUntilDone:NO];
	}
}

@implementation AppDelegate

- (void)dealloc
{
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
	s_pAppDelegate = self;

	m_Thread = nil;
	m_iTerm = 0;
	m_uInstID = 0;
	m_uSessID = 0;
	m_szDevID[0] = '\0';

	self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
	self.viewController = [[ViewController alloc] init];
	self.window.rootViewController = self.viewController;
	self.window.backgroundColor = [UIColor whiteColor];
	[self.window makeKeyAndVisible];
    
	int iY = 0;

	// Input device id.
	iY += 30;
	UILabel *label1 = [[UILabel alloc] initWithFrame:CGRectMake(10, iY, 90, 30)];
	[label1 setTag:1001];
	[label1 setText:@"Device ID:"];
	[self.window addSubview:label1];

	UITextField* textField1 = [[UITextField alloc] initWithFrame:CGRectMake(110, iY, 200, 30)];
	[textField1 setTag:1002];
	[textField1 setBorderStyle:UITextBorderStyleBezel];
	[textField1 setClearButtonMode:UITextFieldViewModeUnlessEditing];
	[self.window addSubview:textField1];

	// Connect buttons.
	iY += 40;
	UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
	[button1 setTag:1003];
	[button1 setFrame:CGRectMake(10, iY, 140, 40)];
	[button1 setTitle:@"Connect" forState:UIControlStateNormal];
	[button1 addTarget:self action:@selector(btnClickConnect:) forControlEvents:UIControlEventTouchUpInside];
	[self.window addSubview:button1];

	UIButton *button2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
	[button2 setTag:1004];
	[button2 setFrame:CGRectMake(170, iY, 140, 40)];
	[button2 setTitle:@"Disconnect" forState:UIControlStateNormal];
	[button2 addTarget:self action:@selector(btnClickDisconnect:) forControlEvents:UIControlEventTouchUpInside];
	[self.window addSubview:button2];

	iY += 50;
	UITextView *textView1 = [[UITextView alloc] initWithFrame:CGRectMake(10, iY, 300, 30)];
	[textView1 setTag:1005];
	[textView1 setText:@"No connect"];
	[self.window addSubview:textView1];

	// Switch control button.
	iY += 60;
	UIButton *button3 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
	[button3 setTag:1006];
	[button3 setFrame:CGRectMake(10, iY, 140, 40)];
	[button3 setTitle:@"Switch On" forState:UIControlStateNormal];
	[button3 addTarget:self action:@selector(btnClickSwitchOn:) forControlEvents:UIControlEventTouchUpInside];
	[self.window addSubview:button3];

	UIButton *button4 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
	[button4 setTag:1007];
	[button4 setFrame:CGRectMake(170, iY, 140, 40)];
	[button4 setTitle:@"Switch Off" forState:UIControlStateNormal];
	[button4 addTarget:self action:@selector(btnClickSwitchOff:) forControlEvents:UIControlEventTouchUpInside];
	[self.window addSubview:button4];

	iY += 50;
	UITextView *textView2 = [[UITextView alloc] initWithFrame:CGRectMake(10, iY, 300, 30)];
	[textView2 setTag:1008];
	[self.window addSubview:textView2];

	// Lan scan button.
	iY += 60;
	UIButton *buttonScan = [UIButton buttonWithType:UIButtonTypeRoundedRect];
	[buttonScan setTag:1010];
	[buttonScan setFrame:CGRectMake(10, iY, 300, 40)];
	[buttonScan setTitle:@"LAN Scan" forState:UIControlStateNormal];
	[buttonScan addTarget:self action:@selector(btnClickLanScan:) forControlEvents:UIControlEventTouchUpInside];
	[self.window addSubview:buttonScan];
    
	iY += 50;
	UITextView *textViewScanResult = [[UITextView alloc] initWithFrame:CGRectMake(10, iY, 300, 60)];
	[textViewScanResult setTag:1011];
	[self.window addSubview:textViewScanResult];

	[self cnntInitialize];

	return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
	// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
	// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
	// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
	// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
	// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
	[self cnntLoginNow];
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
	// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

- (void)applicationWillTerminate:(UIApplication *)application
{
	// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
	[self cnntClean];
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
	[textField resignFirstResponder];
	return YES;
}

-(void)cnntInitialize
{
	if (m_Thread != nil) {
		return;
	}
	
	m_iTerm = 0;
	m_uInstID = 0;
	m_uSessID = 0;
	
	PG_INIT_CFG_S stInitCfg;
	memset(&stInitCfg, 0, sizeof(stInitCfg));
	
	if (pgInitialize(&m_uInstID, PG_MODE_CLIENT, "test", "", "connect.peergine.com:7781",
		"type=0&load=0&addr=relay.peergine.com:443", &stInitCfg, DebugOut) != PG_ERROR_OK)
	{
		dprintf0("Init peergine module failed.\n");
		return;
	}
	
	dprintf0("Init peergine module success.\n");
	[(UITextView *)[self.window viewWithTag:1005] setText:@"Logining ..."];

	m_Thread = [NSThread alloc];
	[m_Thread initWithTarget:self selector:@selector(cnntEventProc:) object:self];
	[m_Thread start];
}

-(void)cnntClean
{
	// Exit thread
	[m_Thread cancel];
	while (m_iTerm == 0) {
		[NSThread sleepForTimeInterval:0.1f];
	}
	m_Thread = nil;
	
	// Disconnect
	if (m_uSessID != 0) {
		pgClose(m_uInstID, m_uSessID);
		m_uSessID = 0;
	}
	
	// Cleanup instance.
	pgCleanup(m_uInstID);
	m_uInstID = 0;
	
	dprintf0("Clean peergine module.");
	[(UITextView *)[self.window viewWithTag:1005] setText:@"Logout"];
}

-(void)cnntLoginNow
{
	// LoginNow.
	if (m_uInstID != 0) {
		pgLoginNow(m_uInstID, 0);
	}
}

-(void)cnntOpen
{
	NSString *devID = [(UITextField *)[self.window viewWithTag:1002] text];
	const char  *pszDevID = [devID UTF8String];
	if (pszDevID == 0 || pszDevID[0] == '\0') {
		return;
	}
	strcpy(m_szDevID, pszDevID);
	dprintf0(pszDevID);

	[(UITextView *)[self.window viewWithTag:1005] setText:@"Connecting ..."];
	int iErr = pgOpen(m_uInstID, m_szDevID, &m_uSessID);
	if (iErr != PG_ERROR_OK) {
		[(UITextView *)[self.window viewWithTag:1005] setText:@"Connect failed"];
		return;
	}
}

-(void)cnntClose
{
	// Disconnect.
	if (m_uSessID != 0) {
		pgClose(m_uInstID, m_uSessID);
		m_uSessID = 0;
	}
	
	[(UITextView *)[self.window viewWithTag:1005] setText:@"Disconnect."];
}

-(void)cnntWrite:(NSString *)sData
{
	if (m_uSessID != 0) {
		const char* pszData = [sData UTF8String];
		if (pszData != 0) {
			int iErr = pgWrite(m_uInstID, m_uSessID, pszData, strlen(pszData), PG_PRIORITY_1);
			if (iErr < PG_ERROR_OK) {
				dprintf0("pgWrite: iErr=%d", iErr);
			}
		}
	}
	else {
		[(UITextView *)[self.window viewWithTag:1008] setText:@"No connect"];
	}
}

-(void)cnntEventProc:(id)pThis
{    
	while (!m_Thread.isCancelled) {

		unsigned int uSessIDNow = 0;
		unsigned int uEventNow = PG_EVENT_NULL;
		unsigned int uPrio = PG_PRIORITY_BUTT;
		int iErr = pgEvent(m_uInstID, &uEventNow, &uSessIDNow, &uPrio, 200);
		if (iErr != PG_ERROR_OK) {
			if (iErr != PG_ERROR_TIMEOUT) {
				dprintf0("Event: iErr=%d\n", iErr);
			}

			continue;
		}
		
		if (uEventNow == PG_EVENT_CONNECT) {
			dprintf0("CONNECT: SessID=%u\n", uSessIDNow);

			const char* pszData = "Request: Hello Apple!";
			int iRet = pgWrite(m_uInstID, uSessIDNow, pszData, strlen(pszData), PG_PRIORITY_1);
			if (iRet < 0) {
				dprintf0("Write1: iRet=%d\n", iRet);
			}

			onCallback("CONNECT?");
		}
		else if (uEventNow == PG_EVENT_CLOSE) {
			dprintf0("CLOSE: SessID=%u\n", uSessIDNow);

			pgClose(m_uInstID, uSessIDNow);
			m_uSessID = 0;

			onCallback("CLOSE?");
		}
		else if (uEventNow == PG_EVENT_READ) {
			dprintf0("READ: SessID=%u, uPrio=%u\n", uSessIDNow, uPrio);

			char szCmd[256] = {0};
			unsigned int uPrio = 0;
			int iRet = pgRead(m_uInstID, uSessIDNow, szCmd, (sizeof(szCmd) - 1), &uPrio);
			if (iRet < PG_ERROR_OK) {
				dprintf0("Read: iErr=%d\n", iRet);
				continue;
			}
			szCmd[iRet] = '\0';

			char szParam[512] = {0};
			sprintf(szParam, "READ?%s", szCmd);
			onCallback(szParam);
		}
		else if (uEventNow == PG_EVENT_WRITE) {
			dprintf0("WRITE: SessID=%u, uPrio=%u\n", uSessIDNow, uPrio);
		}
		else if (uEventNow == PG_EVENT_OFFLINE) {
			dprintf0("OFFLINE: SessID=%u\n", uSessIDNow);

			pgClose(m_uInstID, uSessIDNow);
			m_uSessID = 0;

			onCallback("OFFLINE?");
		}
		else if (uEventNow == PG_EVENT_SVR_LOGIN) {
			dprintf0("SVR_LOGIN: SessID=%u\n", uSessIDNow);
			onCallback("SVR_LOGIN?");
		}
		else if (uEventNow == PG_EVENT_SVR_LOGOUT) {
			dprintf0("SVR_LOGOUT: SessID=%u\n", uSessIDNow);
			onCallback("SVR_LOGOUT?");
		}
		else if (uEventNow == PG_EVENT_LAN_SCAN) {
			dprintf0("LAN_SCAN: SessID=%u\n", uSessIDNow);
			onCallback("LAN_SCAN?");
		}
	}
	
	m_iTerm = 1;
}

-(void)cnntCallback:(NSString *)sParam
{
	const char* pszParam = [sParam UTF8String];
	if (pszParam != 0) {
		char szMeth[128] = {0};
		const char* pszTemp = strchr(pszParam, '?');
		if (pszTemp != 0) {
			unsigned int uSize = pszTemp - pszParam;
			memcpy(szMeth, pszParam, uSize);
			szMeth[uSize] = '\0';
			pszTemp += 1;
		}
		else {
			strcpy(szMeth, pszParam);
			pszTemp = "";
		}
		
		if (strcmp(szMeth, "CONNECT") == 0) {
			[(UITextView *)[self.window viewWithTag:1005] setText:@"Connect success"];
		}
		else if (strcmp(szMeth, "CLOSE") == 0) {
			[(UITextView *)[self.window viewWithTag:1005] setText:@"Disconnect"];
		}
		else if (strcmp(szMeth, "OFFLINE") == 0) {
			[(UITextView *)[self.window viewWithTag:1005] setText:@"Listen side offline"];
		}
		else if (strcmp(szMeth, "READ") == 0) {
			NSString *data = [NSString stringWithUTF8String:pszTemp];
			[(UITextView *)[self.window viewWithTag:1008] setText:data];
		}
		else if (strcmp(szMeth, "SVR_LOGIN") == 0) {
			[(UITextView *)[self.window viewWithTag:1005] setText:@"Login success"];
		}
		else if (strcmp(szMeth, "SVR_LOGOUT") == 0) {
			[(UITextView *)[self.window viewWithTag:1005] setText:@"Logout"];
		}
		else if (strcmp(szMeth, "LAN_SCAN") == 0) {
			PG_LAN_SCAN_S stLanList[8];
			int iErr = pgLanScanResult(m_uInstID, stLanList, 8);
			if (iErr >= PG_ERROR_OK) {
				NSString* sList = @"Scan result:\n";
				for (int i = 0; i < iErr; i++) {
					NSString* sLine = [NSString stringWithFormat:@"ID=%s, Addr=%s\n",
						stLanList[i].szListenID, stLanList[i].szAddr];
					sList = [sList stringByAppendingString:sLine];
				}
				[(UITextView *)[self.window viewWithTag:1011] setText:sList];
			}
			else {
				[(UITextView *)[self.window viewWithTag:1011] setText:@"Get lan scan result failed"];
			}
		}
	}
}

-(IBAction)btnClickConnect:(id)sender
{
	[self cnntOpen];
}

-(IBAction)btnClickDisconnect:(id)sender
{
	[self cnntClose];
}

-(IBAction)btnClickSwitchOn:(id)sender
{
	[(UITextView *)[self.window viewWithTag:1008] setText:@"Switching ..."];
	[self cnntWrite:@"Switching On"];
}

-(IBAction)btnClickSwitchOff:(id)sender
{
	[(UITextView *)[self.window viewWithTag:1008] setText:@"Switching ..."];
	[self cnntWrite:@"Switch Off"];
}

-(IBAction)btnClickLanScan:(id)sender
{
	int iErr = pgLanScanStart(m_uInstID);
	if (iErr != PG_ERROR_OK) {
		[(UITextView *)[self.window viewWithTag:1011] setText:@"LAN scan start failed"];
	}
}

@end
