#define _CRT_SECURE_NO_WARNINGS 1			//vc++のおせっかいな警告を消すマクロ
#define  _CRT_NON_CONFORMING_SWPRINTFS 1	//vc++のおせっかいな警告を消すマクロ

#include <exception>
#include <string>
#include <nlib\nlib.h>
#include <nlib\nlib_define.h>
#include "nlib_stub.h"
#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#include <process.h>
#include <qwerty\windebuger.h>



static void *nlibmemory;
static BROWSERTYPE browserType;
static unsigned int WINAPI commentthread(VOID *usadata);
NicoLiveStream_P NicoLiveStream_new(){

	NicoLiveStream_P rslt = (NicoLiveStream_P)malloc(sizeof(NicoLiveStream));
	ZeroMemory(rslt,sizeof(*rslt));
	rslt->endEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
	rslt->receveEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
	return rslt;
}

VOID NicoLiveStream_delete(NicoLiveStream_P* self){

	NicoLiveStream_disConnect(*self);
	CloseHandle((*self)->endEvent);
	CloseHandle((*self)->receveEvent);
	free(*self);
	*self = NULL;
	return;
}

NicoVideoAuth_P NicoVideoAuth_new(){

	return (NicoVideoAuth_P)malloc(65536);
}

VOID NicoVideoAuth_delete(NicoVideoAuth_P *self){

	free(*self);
	*self= NULL;
}


NLIB_RESULT InitializeNLIB(HINTERNET hInternet){

	nlibmemory = malloc(65536);

	return NLIB_ERR_OK;
}


VOID FinalizeNLIB(){

	free(nlibmemory);
}

NLIB_RESULT NicoVideoAuth_getNicoVideoAuth(NicoVideoAuth_P self,BROWSERTYPE browserType){

	::browserType = browserType;

	return NLIB_ERR_OK;
}

#ifndef TEST_CONNECT_RESULT_CHECK

NLIB_RESULT NicoLiveStream_connect(NicoLiveStream_P self,NicoVideoAuth_P nicoVideoAuth,LPCWSTR url,NicoRecvCallBack callback,LPVOID option){
	
	NLIB_RESULT rslt = NLIB_ERR_OK;

	NicoLiveStream_disConnect(self);

	self->callback = callback;
	self->option = option;
	self->threadHandle = (HANDLE)_beginthreadex(NULL,0,commentthread,self,0,NULL);



	return rslt;
}
#endif

#ifdef TEST_CONNECT_RESULT_CHECK
NLIB_RESULT NicoLiveStream_connect(NicoLiveStream_P self,NicoVideoAuth_P nicoVideoAuth,LPCWSTR url,NicoRecvCallBack callback,LPVOID option){
	
	static NLIB_RESULT rslt = NLIB_ERR_OK;

	rslt++;



	return rslt;
}


#endif

VOID NicoLiveStream_disConnect(NicoLiveStream_P self){

	SetEvent(self->endEvent);
	if(self->threadHandle != INVALID_HANDLE_VALUE){
		WaitForSingleObject(self->threadHandle,INFINITE);
		CloseHandle(self->threadHandle);
	}
	
	
	
	self->threadHandle = NULL;

	ResetEvent(self->endEvent);
	return;
}

StreamStatus_P NicoLiveStream_getStreamStatus(NicoLiveStream_P self){

	self->stream.base_time = 1324709820;
	self->stream.open_time = 1324709820;
	self->stream.end_time = 1324713599;
	self->stream.start_time = 1324710000;
	
	_tcscpy(self->stream.id,TEXT("lv75313550"));
	_tcscpy(self->stream.default_community,TEXT("co1345577"));

	self->stream.is_owner = FALSE;
	self->stream.provider_type = COMMUNITY_PROVIDER_TYPE;
	

	return &self->stream;
}

NLIB_RESULT NicoLiveStream_sendChat(NicoLiveStream_P self,LPCWSTR chatbuf,LPCWSTR *mail,LPCWSTR *extends){


	return 0;
}

void commentthread_inteanal(void* userdata){

	NicoLiveStream_P self = (NicoLiveStream_P)userdata;
	DWORD rslt;
	do{
		rslt = WaitForSingleObject(self->endEvent,500);

		if(rslt != WAIT_TIMEOUT){
			break;
		}

		SetEvent(self->receveEvent);

	}while(TRUE);
	_endthread();
}

VOID NicoLiveStrream_setResFrom(NicoLiveStream_P self,INT_PTR res){

	return;
}


NLIB_RESULT NicoLiveStream_sendOwnerChat(NicoLiveStream_P self,LPCTSTR chatbuf,LPCTSTR *mail,LPCTSTR *extends){

	return NLIB_ERR_OK;
}

unsigned int WINAPI commentthread(VOID *usadata){

	NicoLiveStream_P self = (NicoLiveStream_P)usadata;

	NicoLiveThreadComment threadcomment;
	threadcomment.last_res = TEXT("256");
	threadcomment.server_time = 12345467;
	threadcomment.thread = TEXT("1234567");
	threadcomment.ticket = TEXT("0x12334445");
	self->callback(NICOLIVE_EVENT_RECEVE_CONNECTRESULT,self,self->option,(NICOLIVE_PARAM)&threadcomment,0);

	NicoLiveChat liveChat;
	TCHAR noBuf[sizeof(UINT_PTR) * 8];
	liveChat.anonymity = TEXT("");
	TCHAR user_idBuffer[256];
	liveChat.date = TEXT("1324713598");
	liveChat.locale = TEXT("jp");
	LPTSTR mails[] = {TEXT("184"),NULL};
	liveChat.mail = &mails[0];
	liveChat.mailCount = ARRAY_LENGTH(mails) - 1;
	liveChat.name = TEXT("");
	liveChat.no = noBuf;
	liveChat.premium = TEXT("1");
	liveChat.thread = TEXT("1000254");
	LPCTSTR user_id_format = TEXT("testuser%d");
	liveChat.user_id = user_idBuffer;
	liveChat.vpos = TEXT("8852");
	int commentcount = 0;

	DWORD rslt;
	srand((unsigned int)time(NULL));

	for(int indexfirst = 0; indexfirst < STARTRECEVECOUNT;indexfirst++){
		liveChat.chatBuf = commentcount % 2 == 0 ? TEXT("http://live.nicovideo.jp/watch/lv79715214?alert=1 2545 http://live.nicovideo.jp/watch/lv79715214?alert=1") : TEXT("test @テストユーザ1");
		_stprintf((LPTSTR)liveChat.user_id,user_id_format,rand() % 15);
		commentcount++;
		_stprintf((LPTSTR)liveChat.no,TEXT("%u"),commentcount);
		
		self->callback(NICOLIVE_EVENT_RECEVE_CHAT,self,self->option,(NICOLIVE_PARAM)&liveChat,commentcount);
		
	}
	
	_beginthread(commentthread_inteanal,0,self);
	HANDLE eventarray[] = {self->endEvent,self->receveEvent};
	for(int index = 0,index2; index < RECEVECOUNT;index++){


		for(index2 = 0;index2 < ONERECEVECHATCOUNT;index2++){

			liveChat.chatBuf = commentcount % 2 == 0 ? TEXT("http://live.nicovideo.jp/watch/lv79715214?alert=1 254 http://live.nicovideo.jp/") : TEXT("<font color=FF0000>sm552447 sm1543514 lv25447 </font >@3333");
			_stprintf((LPTSTR)liveChat.user_id,TEXT("%s"),TEXT("0NsZs9X9GFLJaE9Ru3QuV2StCIM"));
			commentcount++;
			_stprintf((LPTSTR)liveChat.no,TEXT("%u"),commentcount);
			
			self->callback(NICOLIVE_EVENT_RECEVE_CHAT,self,self->option,(NICOLIVE_PARAM)&liveChat,commentcount);
			
		}

		self->callback(NICOLIVE_EVENT_RECEVE_CHATSETTLE,self,self->option,100,commentcount);
		ResetEvent(self->receveEvent);
		rslt = WaitForMultipleObjects(ARRAY_LENGTH(eventarray),eventarray,FALSE,INFINITE);
		
		//エラーの場合
		if(rslt == WAIT_OBJECT_0 ){

			goto end;
		}
		
		
		
	}
end:

	_endthreadex(0);
	return 0;
}


//
//ストリームステータス関連
//

///
///ストリームステータスのIDを取得
///
NLIB_DECLSPEC LPCTSTR StreamStatus_getId(StreamStatus_P self){

	return self->id;
}


///
///ストリームステータスのコミュニティ番号を取得
///
NLIB_DECLSPEC LPCTSTR StreamStatus_getDefaultCommunity(StreamStatus_P self){

	return self->default_community;
}


///
///ストリームステータスのプロバイダタイプを取得
///
PROVIDERTYPE StreamStatus_getProviderType(StreamStatus_P self){

	return self->provider_type;
}


///
///ストリームステータスのオーナーフラグを取得
///
BOOL StreamStatus_isOwner(StreamStatus_P self){

	return self->is_owner;
}

///
///ストリームステータスの開始時刻を取得
///
time_t StreamStatus_getStartTime(StreamStatus_P self){

	return self->start_time;
}

///
///ストリームステータスの終了時刻を取得
///
time_t StreamStatus_getEndTime(StreamStatus_P self){

	return self->end_time;
}

///
///ストリームステータスの開場時刻を取得
///
time_t StreamStatus_getOpenTime(StreamStatus_P self){

	return self->open_time;

}

///
///ストリームステータスのベース時刻を取得
///
time_t StreamStatus_getBaseTime(StreamStatus_P self){

	return self->base_time;
}



BOOL NicoLiveStream_isPremium(NicoLiveStream_P self){

	return 0;

}


///
///ハートビートの間隔を設定（ミリ秒)
///
VOID NicoLiveStream_setHeartBeatMsec(NicoLiveStream_P self,DWORD msec){

	

	return;
}

///
///ハートビートの間隔を取得(ミリ秒)
///
DWORD NicoLiveStream_getHeartBeatMsec(NicoLiveStream_P self){

	return 300000;


}

///
///ハートビート有効・無効設定
///
VOID NicoLiveStream_setHeartBeatFlag(NicoLiveStream_P self,BOOL flag){

	return;

}


///
///ハートビート有効フラグ取得
///
BOOL NicoLiveStream_getHeartBeatFlag(NicoLiveStream_P self){

	return FALSE;


}


///
///キープアライブの間隔を設定(ミリ秒)
///
VOID NicoLiveStream_setKeapALiveMsec(NicoLiveStream_P self,DWORD msec){

#ifdef USE_NLIB_KEEPALIVE
	self->chatManager.keepAliveTime = msec;
	WSASetEvent(self->chatManager.setKeepAliveTimeEvent);
#endif
	return;

}

///
///キープアライブの間隔を取得(ミリ秒)
///
DWORD NicoLiveStream_getKeapALiveMsec(NicoLiveStream_P self){

#ifdef USE_NLIB_KEEPALIVE
	return self->chatManager.keepAliveTime;
#else 
	return 0;
#endif

}


///
///キープアライブ有効・無効設定
///
VOID NicoLiveStream_setKeapALiveFlag(NicoLiveStream_P self,BOOL flag){

#ifdef USE_NLIB_KEEPALIVE
	self->chatManager.keapALiveFlag = flag;
#endif
}


///
///キープアライブフラグ取得
///
BOOL NicoLiveStream_getKeapALiveFlag(NicoLiveStream_P self){

#ifdef USE_NLIB_KEEPALIVE
	return self->chatManager.keapALiveFlag;
#else 
	return FALSE;
#endif

}



INT_PTR NicoLiveStream_getResFrom(NicoLiveStream_P self){

	return 0;
}

NLIB_RESULT NicoLiveStream_sendHeartBeat(NicoLiveStream_P self){

	return NLIB_ERR_OK;
}


///
///ストリームステータスのIDを取得
///
LPCTSTR NicoLiveStream_getId(NicoLiveStream_P self){
	static const LPCTSTR rslt = TEXT("lv000002");
	return rslt;
}


///
///ストリームステータスのコミュニティ番号を取得
///
LPCTSTR NicoLiveStream_getDefaultCommunity(NicoLiveStream_P self){
	static const LPCTSTR rslt = TEXT("co1345577");
	return rslt;
}


///
///ストリームステータスのプロバイダタイプを取得
///
PROVIDERTYPE NicoLiveStream_getProviderType(NicoLiveStream_P self){

	return 0;
}


///
///ストリームステータスのオーナーフラグを取得
///
BOOL NicoLiveStream_isOwner(NicoLiveStream_P self){

	return FALSE;
}



///
///ストリームステータスの開始時刻を取得
///
time_t NicoLiveStream_getStartTime(NicoLiveStream_P self){

	return 0;
}

///
///ストリームステータスの終了時刻を取得
///
time_t NicoLiveStream_getEndTime(NicoLiveStream_P self){

	return 0;
}

///
///ストリームステータスの開場時刻を取得
///
time_t NicoLiveStream_getOpenTime(NicoLiveStream_P self){

	return 0;

}

///
///ストリームステータスのベース時刻を取得
///
time_t NicoLiveStream_getBaseTime(NicoLiveStream_P self){

	return 0;
}


///
///ストリームステータスのタイトル取得
///
LPCTSTR NicoLiveStream_getTitle(NicoLiveStream_P self){
#ifdef PLAYERSTATUS_GET_TITLE
	return self->playerStatus.stream.title;
#else
	static const LPCTSTR rslt = TEXT("");
	return rslt;
#endif
}




LPCTSTR NicoVideoAuth_getUserSession(NicoVideoAuth_P self){

	static const  LPCTSTR rslt = TEXT("user_session=user_session_14018634_55619152528064910");
	return rslt;
	
}