module yamalib.auxil.filechecker;

private import std.md5;
private import std.string;

private import y4d_aux.filesys;
private import ytl.y4d_result;

private import kyojintati4d.val.kyojinconst;

private import yamalib.auxil.encryption;
private import yamalib.log.log;

/**
	MD5を使い、ファイルの改ざんを阻止する
*/
class FileChecker {

public :

	/// MD5を元に、ファイルの同一性をチェックする
	static bool checkFileOrigin(char[] filename, ubyte[] md5, int encType) {
		ubyte digest[16];
		ubyte decMD5[];
		
		void[] data = cast(void[]) FileSys.read(filename);
		
		if (data is null || md5 is null || md5.length != 16) {
			Log.printError("MD5 DATA error");
			return false;
		}
		
		switch ( encType )  {
		case Encryption.TYPE.ROW_DATA:
			decMD5 = md5;
			break;
			
		case Encryption.TYPE.XOR:
			Encryption.decXOR(decMD5, md5, KyojinConst.C_K2C_INFO_KYOJINTACHI);
			break;
		default:
			assert(false);
		}
		
		// チェック対象データのMD5算出
		std.md5.sum( digest, data );

		return identMD5(digest, decMD5);
	}
	
	
	/// ファイルを元にMD5ダイジェストを計算し、ダイジェストをファイルに保存する
	static bool createMD5File(char[] inFilename, char[] saveFilename, int encType) 
	/**
		dgがnullでなければそれを用いて、暗号化を施し、暗号化値を保存する
	*/
	{
		ubyte digest[16];
		ubyte encDigest[];
		
		void[] data = cast(void[]) FileSys.read(inFilename);
		
		if (data is null) {
			return false;
		}

		// MD5ダイジェスト計算		
		std.md5.sum( digest, data );
		
		debug {
			Log.print( "created Digest" );
			char[] strDebug;
			foreach ( inout ubyte bNum; digest ) {
				strDebug ~= .toString(bNum) ~ " ";
			}
			Log.print("%s", strDebug);
		}
		
		switch ( encType )  {
		case Encryption.TYPE.ROW_DATA:
			encDigest = digest;
			break;
			
		case Encryption.TYPE.XOR:
			Encryption.encXOR(encDigest, digest, KyojinConst.C_K2C_INFO_KYOJINTACHI);
			break;
		default:
			assert(false);
		}
		
		return cast(bool) (FileSys.write( saveFilename, cast(void[]) encDigest ) 
			== y4d_result.no_error);
	}
	
	/// ファイルに保存されたMD5ダイジェストを読みこむ
	static ubyte[] readMD5Digest(char[] filename) {
		return cast(ubyte[]) FileSys.read(filename);
	}


private :


	/// MD5ダイジェストを比較し、同一ならばtrueを返す
	static bool identMD5( ubyte[] src, ubyte[] dst ) {
		for (int i = 0; i < 16; ++i) {
			if (src[i] != dst[i]) {
				Log.print("digest not equals!");
				return false;
			}
		}
		return true;
	} 

	this() {
		// インスタンス不可
	}

}
