#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <memory.h>

int ReadIniFile(char *Section_, char *Param_, char *RetBuff_, char *IniFile_);
void CreateAisConnectCommand(char *RetCommand_, char *IpAdd_, char *Port_, char *IniFile_);
int CreateRecvSocket(char *IpAdd_, char *Port_);
int StrRep(char *Buff_, char *OldWord_, char *NewWord_);
int ResetLastData();
int SepVdmData(char *VdmData_);
int CallAnalysProg(int Type_, char *Data_, char *WgsNum_, char *ConstID_, char *ToFolder_);
int RetCharIndex(char *Word_);
int DeleteOldMmsiFile(int Minutes_);

// 前回データのDatCount, Number-------------------
int LastDataCount;
int LastNumber;
char AnaData[1024];
char WgsNum[32];
//------------------------------------------------

//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//	Main()
//	引数	：	int			argc			コマンドライン引数の数
//				char		argv[]			コマンドライン引数
//	戻り値	：	int			0
//	備考	：	
//	更新	：	2011/08/26 T.Teraoka
//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
int main(int argc, char *argv[])
{
	char IniFile[1024];		// 設定FileのPath
	char EndFlag[32];		// 終了フラグ
	char ConstID[32];		// 工事ID
	//char ToFolder[512];	// 配信先フォルダ
	
	// 起動時に設定FileのPathを受け取る
	if (argc < 2)
	{
		printf("設定FileのPathが指定されていません\n");
		return -1;
	}
	else
	{
		memset(&IniFile, 0x00, sizeof(IniFile));
		sprintf(IniFile, "%s", argv[1]);
	}
	
	// 各種設定読み込み
	//memset(&ToFolder, 0x00, sizeof(ToFolder));
	memset(&ConstID, 0x00, sizeof(ConstID));
	//ReadIniFile("To", "Folder", ToFolder, IniFile);
	ReadIniFile("Config", "KoujiID", ConstID, IniFile);
	
	// IP, Port, AIS接続情報の取得
	char IpAdd[256];
	char Port[32];
	memset(&IpAdd, 0x00, sizeof(IpAdd));
	memset(&Port, 0x00, sizeof(Port));
	ReadIniFile("Config", "IpAdd", IpAdd, IniFile);
	ReadIniFile("Config", "Port", Port, IniFile);

	char ToFolder[512] = "";
	if (ReadIniFile("To", "Folder", ToFolder, IniFile) != 0)
	{
		printf("[ToFolder]の読み込み失敗\n");
	}

	
	// AIS受信コマンドを作成
	char AisCommand[1024];
	memset(&AisCommand, 0x00, sizeof(AisCommand));
	CreateAisConnectCommand(AisCommand, IpAdd, Port, IniFile);
	
	// 測地系を取得
	memset(&WgsNum, 0x00, sizeof(WgsNum));
	ReadIniFile("Config", "WgsNum", WgsNum, IniFile);
	
	int RecvSock = CreateRecvSocket(IpAdd, Port);
	
	// 特定コマンドを投げる
	printf("コマンド送信---------------------\n");
	printf("%s\n", AisCommand);
	printf("---------------------------------\n");
	
	int Ret = send(RecvSock, AisCommand, strlen(AisCommand), MSG_DONTWAIT);
	
	char ReadBuff[1024];
	// 送られてくるデータを受信
	for(;;)
	{
		// 終了フラグをCheck
		memset(&EndFlag, 0x00, sizeof(EndFlag));
		ReadIniFile("Config", "EndFlag", EndFlag, IniFile);
		
		if (atoi(EndFlag) == 0)
		{
			memset(&ReadBuff, 0x00, sizeof(ReadBuff));
			recv(RecvSock, &ReadBuff, sizeof(ReadBuff), 0);
			
			//printf("read=>%s\n", ReadBuff);
			char *Token;
			char *SavePtr;
			char *SepWord = "\r\n";
			
			Token = strtok_r(ReadBuff, SepWord, &SavePtr);
			while(Token != NULL)
			{
				Token = strtok_r(NULL, SepWord, &SavePtr);
				if (Token != NULL)
				{
					//printf("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
					//printf("%s\n", Token);
					//printf("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
					
					char VdmData[512];
					memset(&VdmData, 0x00, sizeof(VdmData));
					sprintf(VdmData, "%s", Token);
					
					// 複数行データが存在するためさらに分割------------------------------------------------------------
					if (strstr(VdmData, "!AIVDM") != NULL && strstr(VdmData, "POST /AISDist/serve/serveData HTTP/1.1") == NULL)
					{
						int Ret = SepVdmData(VdmData);
						if (Ret == 1)
						{
							// 解析
							CallAnalysProg(1, AnaData, WgsNum, ConstID, ToFolder);
							
							// 初期化
							ResetLastData();
						}
						else if (Ret == -1)
						{
							// 初期化
							ResetLastData();
						}
					}
					//-------------------------------------------------------------------------------------------------
				}
			}
		}
		else
		{
			break;
		}
		// 古いファイルを削除するコマンドを発行-----------------
		//DeleteOldMmsiFile(5);
		//------------------------------------------------------
	}
	close(RecvSock);
	printf("終了\n");
}

//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//	更新されないMMSIファイルを削除
//	関数名	：	DeleteOldMmsiFile
//	引数	：	int			Minutes_		指定分以上更新されないファイルを削除
//	戻り値	：	int			0				
//	備考	：	
//	更新	：	2011/09/01 T.Teraoka
//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
int DeleteOldMmsiFile(int Minutes_)
{
	char SysCm[512] = "";
	sprintf(SysCm, "find ./mmsi/* -cmin +%d | xargs rm -f &", Minutes_);
	system(SysCm);
	return 0;
}

//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//	解析exeを呼び出す
//	関数名	：	CallAnalysProg
//	引数	：	char		*Data_			解析対象データ
//				char		*WgsNum_		測地系
//				char		*ConstID_		工事ID
//	戻り値	：	int 		0
//	備考	：	
//	更新	：	2011/08/26 T.Teraoka
//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
int CallAnalysProg(int Type_, char *Data_, char *WgsNum_, char *ConstID_, char *ToFolder_)
{
	char SysCm[512] = "";
	switch(Type_)
	{
		case 0:
			//sprintf(SysCm, "./DecodeVdm.exe '%s' '%s' '%s' &", Data_, WgsNum_, ConstID_);
			break;
		case 1:
			// 配信先フォルダの読み込み
			sprintf(SysCm, "./AnalysAisDat.exe '%s' '%s' '%s' &", Data_, ConstID_, ToFolder_);
			break;
		default:
			break;
	}
	printf("%s\n", SysCm);
	//system(SysCm);
	return 0;
}

//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//	AIVDMデータを分割する
//	関数名	：	SepVdmData
//	引数	：	char		*VdmData_		VDMデータ
//	戻り値	：	int			0				次のデータを待つ
//							1				解析確定
//							-1				ERORR
//	備考	：	
//	更新	：	2011/08/26 T.Teraoka
//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
int SepVdmData(char *VdmData_)
{
	int IndexVdm = 0;
	char *VdmToken;
	char *SepWordVdm = ",";
	char SepVdmData[6][256];
	
	int iCount = 0;
	for(iCount = 0; iCount < 6; iCount++)
	{
		memset(&SepVdmData[iCount], 0x00, sizeof(SepVdmData[iCount]));
	}
	StrRep(VdmData_, ",,", ", ,");
	
	VdmToken = strtok(VdmData_, SepWordVdm);
	sprintf(SepVdmData[IndexVdm], "%s", VdmToken);
	IndexVdm++;
	while(VdmToken != NULL)
	{
		VdmToken = strtok(NULL, SepWordVdm);
		if (VdmToken != NULL)
		{
			sprintf(SepVdmData[IndexVdm], "%s", VdmToken);
			IndexVdm++;
		}
	}
	
	int DataCount = atoi(SepVdmData[1]);
	int Number = atoi(SepVdmData[2]);
	if (Number == 1)
	{
		if (DataCount == 1)
		{
			// 解析
			sprintf(AnaData, "%s", SepVdmData[5]);
			return 1;
		}
		else
		{
			// 次のデータ待ち
			sprintf(AnaData, "%s", SepVdmData[5]);
		}
	}
	else
	{
		if ((LastNumber + 1) == Number)
		{
			// データを追加
			strcat(AnaData, SepVdmData[5]);
			if (Number == DataCount)
			{
				// 複数行解析
				return 1;
			}
		}
		else
		{
			return -1;
			
		}
	}
	LastDataCount = DataCount;
	LastNumber = Number;
	return 0;
}

//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//	前回変数を初期化
//	関数名	：	ResetLastData
//	引数	：	
//	戻り値	：	なし
//	備考	：	
//	更新	：	2011/08/26 T.Teraoka
//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
int ResetLastData()
{
	LastDataCount = 0;
	LastNumber = 0;
	memset(AnaData, 0x00, sizeof(AnaData));
}

//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//	指定ファイルのパラメータを取得する
//	関数名	：	ReadIniFile
//	引数	：	char		*Section_		セクション名[使用しない]
//				char		*Param_			パラメータキー名
//				char		*RetBuff_		取得パラメータ格納変数
//				char		*IniFile_		設定ファイルパス
//	戻り値	：	int			0				設定値取得成功
//							-1				設定値取得失敗
//	備考	：	
//	更新	：	2011/08/25 T.Teraoka
//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
int ReadIniFile(char *Section_, char *Param_, char *RetBuff_, char *IniFile_)
{
	int Length;
	char *Point;
	FILE *FpIni;
	char GetBuff[512];
	
	memset(&GetBuff, 0x00, sizeof(GetBuff));
	
	FpIni = fopen(IniFile_, "r");
	if (FpIni == NULL)
	{
		return -1;
	}
	else
	{
		while(fgets(GetBuff, sizeof(GetBuff), FpIni) != NULL)
		{
			if (strstr(GetBuff, Param_))
			{
				Length = strlen(GetBuff);
				Point = strchr(GetBuff, '=');
				if (Point != NULL)
				{
					strncpy(RetBuff_, GetBuff + (Point - GetBuff + 1), Length - (Point - GetBuff + 1) - 1);
				}
			}
			memset(&GetBuff, 0x00, sizeof(GetBuff));
		}
		fclose(FpIni);
	}
	if (strcmp(RetBuff_, "") == 0)
	{
		return -1;
	}
	return 0;
}

//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//	AISデータを取得するためのコマンドを作成する
//	関数名	：	CreateAisConnectCommand
//	引数	：	char		*RetCommand_	セクション名[使用しない]
//				char		*IniFile_
//	戻り値	：	なし
//	備考	：	
//	更新	：	2011/08/25 T.Teraoka
//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
void CreateAisConnectCommand(char *RetCommand_, char *IpAdd_, char *Port_, char *IniFile_)
{
	char AisUserName[32] = "";
	char AisPass[32] = "";
	char AisCom[256] = "";
	
	memset(&AisUserName, 0x00, sizeof(AisUserName));
	memset(&AisPass, 0x00, sizeof(AisPass));
	memset(&AisCom, 0x00, sizeof(AisCom));
	
	ReadIniFile("Ais", "UserName", AisUserName, IniFile_);
	ReadIniFile("Ais", "Pass", AisPass, IniFile_);
	
	sprintf(AisCom, "userName=%s&password=%s", AisUserName, AisPass);
	int AisComLength = strlen(AisCom);
	
	sprintf(RetCommand_, "POST /AISDist/serve/serveData HTTP/1.1\r\nContent-Type: application/x-www-form-urlencoded\r\nUser-Agent: AISClient\r\nHost: %s:%s\r\nContent-Length:%d\r\nCache-Control: no-cache\r\n\r\nuserName=%s&password=%s\r\n", IpAdd_, Port_, AisComLength, AisUserName, AisPass);
}

//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//	Socketを生成, 接続を行う
//	関数名	：	CreateRecvSocket
//	引数	：	char		*IpAdd_		IPアドレス
//				char		*Port_		ポート
//	戻り値	：	なし
//	備考	：	
//	更新	：	2011/08/25 T.Teraoka
//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
int CreateRecvSocket(char *IpAdd_, char *Port_)
{
	// Socketを生成
	int Sock = socket(PF_INET, SOCK_STREAM, 0);
	
	// 構造体にIPアドレス、ポートをSET
	struct sockaddr_in Add;
	Add.sin_family = PF_INET;
	Add.sin_addr.s_addr = inet_addr(IpAdd_);
	Add.sin_port = htons(atoi(Port_));
	
	// 生成したSocketを接続
	int Res = connect(Sock, (struct sockaddr *)&Add, sizeof(Add));
	if(Res == -1)
	{
		return -1;
	}
	return Sock;
}

//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//	文字列の置換を行う
//	関数名	：	StrRep
//	引数	：	char		*Buff_		文字列
//				char		*OldWord_	対象文字列
//				char		*NewWord_	置換文字列
//	戻り値	：	int			0			成功
//							-1			失敗
//	備考	：	まとめて複数の置換は不可能
//	更新	：	2011/08/25 T.Teraoka
//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
int StrRep(char *Buff_, char *OldWord_, char *NewWord_)
{
	char *Poi;
	size_t OldLen;
	size_t NewLen;
	
	OldLen = strlen(OldWord_);
	NewLen = strlen(NewWord_);
	
	if (OldLen == 0 || (Poi = strstr(Buff_, OldWord_)) == NULL)
	{
		return -1;
	}
	memmove(Poi + NewLen, Poi + OldLen, strlen(Buff_) - (Poi + OldLen - Buff_) + 1);
	memcpy(Poi, NewWord_, NewLen);
	return 0;
}

