#include "stdafx.h"
#include "rnsf7.h"
#include "mainwindow.h"
#include "sakura.h"
#include "about.h"
#include "commfunc.h"

#define BUFSIZE 2090

static volatile HWND ghWnd;
static volatile bool flag = 0, sn_check = 0;
#define SetStatus(t) SendMessage( ghWnd, R7MW_STATUS_BAR, 2, (LPARAM)t );

static void _UpdateCheck(void *_bootflag)
{
	bool bootflag = ((_bootflag == (LPVOID)1)?1:0);
	SOCKET s = INVALID_SOCKET;		// HTTP通信用ソケット
	char *proxyserver = NULL, *proxyport = NULL;	// プロキシサーバとポート
	bool autoclose = 1;				// 確認して更新版がありサイトを開いたらRnsf7を終了する
	bool betaupdatecheck = 0;		// 開発中のバージョンも検出対象にする
	bool minorupdatecheck = 0;		// 小数部の変化のみを検出対象とする
	UINT timeout = 6;				// HTTPタイムアウトまでの秒数
	REG  reg;

	flag = 1; // セマフォ
	if ( reg.OpenKey( HKEY_CURRENT_USER, RNSF7REGKEY ) ) {
		proxyserver = reg.new_ReadString( "ProxyServer", NULL );
		proxyport = reg.new_ReadString( "ProxyPort", "80" );
		autoclose = reg.ReadInteger( "AutoClose", 1 ) ? true : false;
		betaupdatecheck = reg.ReadInteger( "BetaUpdateCheck", 0 ) ? true : false;
		minorupdatecheck = reg.ReadInteger( "MinorUpdateCheck", 0 ) ? true : false;
		timeout = reg.ReadInteger( "httpTimeout", 6 );
		reg.CloseKey();
	}

	// もし小数部のみしかチェックしない場合は、開発中のバージョンの検出は行わない
	if (minorupdatecheck) betaupdatecheck = false;

	sn_check = 0;
	if (bootflag == 0) {
		SetStatus( "サーバへ接続中..." );
	}
	if (0 == OpenSocket( (proxyserver && proxyserver[0] && proxyport)?proxyserver:"www.inasoft.org", (proxyserver && proxyserver[0] && proxyport)?proxyport:"80", &s )) {
		if (s != INVALID_SOCKET) {
			char buf[BUFSIZE+20], *p;
			DWORD starttime;
			int  i, j;

			if (bootflag == 0 || sn_check) {
				SetStatus("アップデート情報を要求中...");
			}
			Sends(&s, (proxyserver && proxyserver[0])?"GET http://www.inasoft.org/update.txt HTTP/1.1\r\nUser-Agent: sakuralib [ja] (Rnsf7)\r\nHost: www.inasoft.org\r\n\r\n":
					                                    "GET /update.txt HTTP/1.0\r\nUser-Agent: sakuralib [ja] (Rnsf7)\r\nHost: www.inasoft.org\r\n\r\n");
			if (bootflag == 0 || sn_check) {
				SetStatus("アップデート情報を取得中...");
			}

			// "dev7rnsf:?????." または "ver7rnsf:?????." を探す
			starttime = GetTickCount();
			ZeroMemory( buf, BUFSIZE+20 );
			i = 0;
			p = NULL;
			do {
				j = ReceiveSocket( &s, buf+i, BUFSIZE-i );
				if ( j > 0 ) {
					p = strstr(buf, betaupdatecheck?"dev7rnsf:":"ver7rnsf:");
					if ( p && '0' <= p[9] && p[9] <= '9' && '0' <= p[10] && p[10] <= '9' && '0' <= p[11] && p[11] <= '9' && '0' <= p[12] && p[12] <= '9' && '0' <= p[13] && p[13] <= '9' && p[14] == '.' ) {
						p += 9;
						break;
					}
					p = NULL;
					i += j;
				}
			} while( i < BUFSIZE && (GetTickCount() - starttime)/1000 <= timeout );
			CloseSocket( &s );
			
			if (p == NULL) {
				SetStatus("アップデート情報を取得できませんでした。");
			}
			else {
				UINT netversion = atoi(p);
				UINT nowversion = getReleaseNumber();

				if (minorupdatecheck) {
					// 小数部の変化しか確認しない
					netversion /= 100;
					nowversion /= 100;
				}

				if (nowversion < netversion) {
					int i;

					SetStatus("現在実行中のバージョンより新しいバージョンが公開されています。");
					if (bootflag) {
						i = MessageBox(ghWnd, autoclose?"現在実行中のバージョンより新しいバージョンが見つかりました。\nINASOFTのWebサイトを表示しますか?\n\n[キャンセル]を押すと、自動通知機能をOFFにします。\n(サイトを開くと、"SOFTWARENAME"は自動的に終了します)"
						                                :"現在実行中のバージョンより新しいバージョンが見つかりました。\nINASOFTのWebサイトを表示しますか?\n\n[キャンセル]を押すと、自動通知機能をOFFにします。\n(このまま"SOFTWARENAME"をアップデートする場合は、ダウンロード前に、現在動作中の"SOFTWARENAME"を終了しておいて下さい)", "インターネット経由で更新確認",MB_YESNOCANCEL | MB_ICONQUESTION);
					}
					else {
						i = MessageBox(ghWnd, autoclose?"現在実行中のバージョンより新しいバージョンが見つかりました。\nINASOFTのWebサイトを表示しますか?\n\n(サイトを開くと、"SOFTWARENAME"は自動的に終了します)"
							                            :"現在実行中のバージョンより新しいバージョンが見つかりました。\nINASOFTのWebサイトを表示しますか?\n\n(このまま"SOFTWARENAME"をアップデートする場合は、ダウンロード前に、現在動作中の"SOFTWARENAME"を終了しておいて下さい)", "インターネット経由で更新確認", MB_YESNO | MB_ICONQUESTION);
					}
					switch (i) {
						case IDYES:
							{
								TCHAR sysdir[MAX_PATH*2] = "\\";
								GetSystemDirectory(sysdir, _countof(sysdir));

								SetCurrentDirectory(sysdir); // カレントディレクトリのDLLが悪さをするといけないので、一時的にCD
								HINSTANCE hResult = ShellExecute(ghWnd, "open", "http://www.inasoft.org/",NULL,sysdir,SW_SHOWNORMAL);
								SetCurrentDirectoryOwnDir();

								if ((HINSTANCE)32 >= hResult) {
									MessageBox(ghWnd, "ブラウザの起動に失敗しました。\nブラウザを起動し、http://www.inasoft.org/ を開いて下さい。", "インターネット経由で更新確認", MB_OK | MB_ICONSTOP);
								}
								else {
									if ( autoclose ) {
										SendMessage( ghWnd, WM_DESTROY, 0, 0 );
									}
								}
							}
							break;

						case IDCANCEL:
							if ( reg.OpenKey( HKEY_CURRENT_USER, RNSF7REGKEY, TREG_OPEN_CREATE ) ) {
								reg.DeleteValue( "AutoUpdateCheck" );
								reg.CloseKey();
							}
							else {
								dispErrorMessage(ghWnd, MB_OK | MB_ICONSTOP, "レジストリへの書き込み中エラー", "レジストリキー'HKEY_CURRENT_USER\\", RNSF7REGKEY,
												 "'を書き込みアクセスで開こうとしてエラーになりました。自動通知機能をOFFにできません。\nAPIが報告した原因：", getLastErrorString(tRegGetLastError()), NULL, NULL);
							}
							break;
					}
					SetStatus(NULL);
				}
				else if (nowversion > netversion) {
					if (bootflag == 0 || sn_check) {
						SetStatus("現在実行中のバージョンは未公開のものです。");
					}
				}
				else {
					if (bootflag == 0 || sn_check) {
						SetStatus("新しいバージョンは見つかりませんでした。現在実行中のバージョンは最新です。");
					}
				}
			}
		}
		else {
			if (bootflag == 0 || sn_check) {
				SetStatus("サーバとの接続に失敗しました。");
			}
		}
	}
	else {
		if (bootflag == 0 || sn_check) {
			SetStatus("サーバとの接続に失敗しました。");
		}
	}

	safedelete(proxyserver);
	safedelete(proxyport);

	flag = 0;
	sn_check = 0;

	_endthread();
}

// UpdateCheck : インターネット経由で更新の確認
// hWnd : 呼び出し側のウィンドウハンドル
// flag : 逐一状況をステータスバーに表示するか( 起動時の自動確認では flag = 1 )
void UpdateCheck( HWND hWnd, int _bootflag )
{
	if (flag == 0) { // flag : _UpdateCheck内で設定しているセマフォ
		ghWnd = hWnd;
#pragma warning( disable : 4312 )
		if ( -1 == _beginthread( _UpdateCheck, 0, (void *)_bootflag ) ) {
#pragma warning( default : 4312 )
			MessageBox(hWnd, "アップデートチェック用のスレッドの生成に失敗しました。", "更新確認", MB_OK | MB_ICONSTOP);
		}
	}
	else { // flag == 1 : すでにチェック中
		sn_check = 1;
		SetStatus("アップデート情報を取得中です...");
	}
}
