Namespace System
Namespace IO

/*
@brief ファイルのアクセス方法を表す
*/
Enum FileAccess
	Read      = GENERIC_READ
	ReadWrite = GENERIC_READ Or GENERIC_WRITE
	Write     = GENERIC_WRITE
End Enum

/*
@brief ファイルの属性を表す
*/
Enum FileAttributes
	Archive           = FILE_ATTRIBUTE_ARCHIVE
	Compressed        = FILE_ATTRIBUTE_COMPRESSED
	Device            = FILE_ATTRIBUTE_DEVICE
	Directory         = FILE_ATTRIBUTE_DIRECTORY
	Encrypted         = FILE_ATTRIBUTE_ENCRYPTED
	Hidden            = FILE_ATTRIBUTE_HIDDEN
	Normal            = FILE_ATTRIBUTE_NORMAL
	NotContentIndexed = FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
	Offline           = FILE_ATTRIBUTE_OFFLINE
	ReadOnly          = FILE_ATTRIBUTE_READONLY
	ReparsePoint      = FILE_ATTRIBUTE_REPARSE_POINT
	SparseFile        = FILE_ATTRIBUTE_SPARSE_FILE
	System            = FILE_ATTRIBUTE_SYSTEM
	Temporary         = FILE_ATTRIBUTE_TEMPORARY
End Enum

/*
@brief ファイルの作成モードを表す
*/
Enum FileMode
	Append       = OPEN_ALWAYS
	Create       = CREATE_ALWAYS
	CreateNew    = CREATE_NEW
	Open         = OPEN_EXISTING
	OpenOrCreate = OPEN_ALWAYS
	Truncate     = TRUNCATE_EXISTING
End Enum

/*
@brief ファイルの共有を表す
*/
Enum FileShare
	None       = 0
	Read       = FILE_SHARE_READ
	Write      = FILE_SHARE_WRITE
	ReadWrite  = FILE_SHARE_READ Or FILE_SHARE_WRITE
	DeleteFile = FILE_SHARE_DELETE
End Enum

/*
@brief  ファイルの操作,情報を取得するクラス
@date   2008/03/13
@author OverTaker
*/

Imports System.Collections.Generic

Class File
Public

	'----------------------------------------------------------------
	' パブリック　メソッド
	'----------------------------------------------------------------

	/*
	@brief ファイルにテキストを追加する
	@param ファイルパス
	@param 追加するテキスト
	*/
	Static Sub AppendAllText( path As String, contents As String )
		Dim stream = AppendText(path) As StreamWriter
		stream.Write(contents)
		stream.Close()
	End Sub

/*	Static Sub AppendAllText( path As String, contents As String, encoding As Encoding )
		' TODO: 実装
	End Sub */

	/*
	@brief  ファイルにテキストを追加するストリームを作成する
	@param  ファイルパス
	@return ストリームライター
	*/
	Static Function AppendText( path As String ) As StreamWriter
		Return New StreamWriter(Open(path, FileMode.Append))
	End Function

	/*
	@brief  ファイルをコピーする(上書きできない)
	@param  コピー元のファイルパス
	@param  コピー先のファイルパス
	*/
	Static Sub Copy( sourceFileName As String, destFileName As String )
		Copy(sourceFileName, destFileName, False)
	End Sub

	/*
	@brief  ファイルをコピーする
	@param  コピー元のファイルパス
	@param  コピー先のファイルパス
	@param  上書きする場合True,しない場合False
	*/
	Static Sub Copy( sourceFileName As String, destFileName As String, overwrite As Boolean )
		If Not CopyFile(Path.GetFullPath(sourceFileName), Path.GetFullPath(destFileName), overwrite) Then
			Throw New IOException( "FileInfo: Failed to CopyFile." )
		End If
	End Sub

	/*
	@brief  新しいファイルを作成し、そのストリームを取得する
	@param  ファイルパス
	@return ファイルストリーム
	*/
	Static Function Create( path As String ) As FileStream
		Return New FileStream(path, FileMode.CreateNew, FileAccess.ReadWrite)
	End Function

/*	Static Function Create( path As String, bufferSize As Long ) As FileStream
		' TODO: 実装
	End Function */

/*	Static Function Create( path As String, bufferSize As Long, options As FileOptions ) As FileStream
		' TODO: 実装
	End Function */

/*	Static Function Create( path As String, bufferSize As Long, options As FileOptions, fileSecurity As FileSecurity ) As FileStream
		' TODO: 実装
	End Function */

/*	Static Function CreateText( path As String ) As StreamWriter
		' TODO: 実装
	End Function*/

/*	Static Sub Decrypt( path As String )
		' TODO: 実装
	End Sub*/

	/*
	@brief ファイルを削除する
	@param ファイルパス
	*/
	Static Sub Delete( path As String )
		If Not DeleteFile(Path.GetFullPath(path)) Then
			Throw New IOException("File.Delete: Failed to DeleteFile.")
		End If
	End Sub

/*	Static Sub Encrypt( path As String )
		' TODO: 実装
	End Sub*/

	/*
	@brief  ファイルが存在するかどうかを取得する
	@param  ファイルパス
	@retval True  存在する
	@retval False 存在しない
	*/
	Static Function Exists( path As String ) As Boolean
		Dim data As WIN32_FIND_DATA
		Dim hFind = FindFirstFile(ToTCStr(Path.GetFullPath(path)), data)
		FindClose(hFind)

		If hFind <> INVALID_HANDLE_VALUE Then
			Return True
		Else
			Return False
		End If
	End Function

/*	Static Function GetAccessControl( path As String ) As FileSecurity
		' TODO: 実装
	End Function */

/*	Static Function GetAccessControl( path As String, includeSections As AccessControlSections ) As FileSecurity
		' TODO: 実装
	End Function */

	/*
	@brief  ファイルの属性を取得する
	@param  ファイルパス
	@return ファイル属性
	*/
	Static Function GetAttributes( path As String ) As FileAttributes
		Return New FileAttributes(getFileData(path).dwFileAttributes As Long, "FileAttributes")
	End Function

	/*
	@brief  ファイルの作成日時を取得する
	@param  ファイルパス
	@return 作成日時
	*/
	Static Function GetCreationTime( path As String ) As DateTime
		Return System.DateTime.FromFileTime(getFileData(path).ftCreationTime)
	End Function

	/*
	@brief  ファイルの作成日時をUTC時刻で取得する
	@param  ファイルパス
	@return 作成日時
	*/
	Static Function GetCreationTimeUtc( path As String ) As DateTime
		Return System.DateTime.FromFileTimeUtc(getFileData(path).ftCreationTime)
	End Function

	/*
	@brief  ファイルの最終アクセス日時を取得する
	@param  ファイルパス
	@return 最終アクセス日時
	*/
	Static Function GetLastAccessTime( path As String ) As DateTime
		Return System.DateTime.FromFileTime(getFileData(path).ftLastAccessTime)
	End Function

	/*
	@brief  ファイルの最終アクセス日時をUTC時刻で取得する
	@param  ファイルパス
	@return 最終アクセス日時
	*/
	Static Function GetLastAccessTimeUtc( path As String ) As DateTime
		Return System.DateTime.FromFileTimeUtc(getFileData(path).ftLastAccessTime)
	End Function

	/*
	@brief  ファイルの最終書き込み日時を取得する
	@param  ファイルパス
	@return 最終書き込み日時
	*/
	Static Function GetLastWriteTime( path As String ) As DateTime
		Return System.DateTime.FromFileTime(getFileData(path).ftLastWriteTime)
	End Function

	/*
	@brief  ファイルの最終書き込み日時をUTC時刻で取得する
	@param  ファイルパス
	@return 最終書き込み日時
	*/
	Static Function GetLastWriteTimeUtc( path As String ) As DateTime
		Return System.DateTime.FromFileTimeUtc(getFileData(path).ftLastWriteTime)
	End Function

	/*
	@brief  ファイルを移動する
	@param  移動元のファイルパス
	@param  移動先のファイルパス
	*/
	Static Sub Move( sourceFileName As String, destFileName As String )
		If Not MoveFile(Path.GetFullPath(sourceFileName), Path.GetFullPath(destFileName)) Then
			Throw New IOException("File.Move: Failed to MoveFile.")
		End If
	End Sub

	/*
	@brief  ファイルストリームを作成する
	@param  ファイルパス
	@param  ファイルモード
	@return ファイルストリーム
	*/
	Static Function Open( path As String, mode As FileMode ) As FileStream
		Return New FileStream(path, mode)
	End Function

	/*
	@brief  ファイルストリームを作成する
	@param  ファイルパス
	@param  ファイルモード
	@param  ファイルアクセス
	@return ファイルストリーム
	*/
	Static Function Open( path As String, mode As FileMode, access As FileAccess ) As FileStream
		Return New FileStream(path, mode, access)
	End Function

	/*
	@brief  ファイルストリームを作成する
	@param  ファイルパス
	@param  ファイルモード
	@param  ファイルアクセス
	@param  ファイル共有
	@return ファイルストリーム
	*/
	Static Function Open( path As String, mode As FileMode, access As FileAccess, share As FileShare ) As FileStream
		Return New FileStream(path, mode, access, share)
	End Function

	/*
	@brief  読み取り専用のファイルストリームを作成する
	@param  ファイルパス
	@return ファイルストリーム
	*/
	Static Function OpenRead( path As String ) As FileStream
		Return Open(path, FileMode.Open, FileAccess.Read, FileShare.Read)
	End Function

	/*
	@brief  読み取り専用のストリームを作成する
	@param  ファイルパス
	@return ストリームリーダー
	*/
	Static Function OpenText( path As String ) As StreamReader
		Return New StreamReader(path)
	End Function

	/*
	@brief  書き込み専用のファイルストリームを作成する
	@param  ファイルパス
	@return ファイルストリーム
	*/
	Static Function OpenWrite( path As String ) As FileStream
		Return Open(path, FileMode.Open, FileAccess.Write)
	End Function

/*	Static Function ReadAllBytes( path As String ) As *Byte
		' TODO: 実装
	End Function*/

	/*
	@brief  ファイルのすべての行を読み取る
	@param  ファイルパス
	@return 各行の文字列が格納されたリスト
	*/
	Static Function ReadAllLines( path As String ) As List<String>
		Dim stream = New StreamReader(path)
		Dim readLines As List<String>
		Dim readLine = stream.ReadLine() As String
		While Not ActiveBasic.IsNothing(readLine)
			readLines.Add(readLine)
			readLine = stream.ReadLine()
		Wend
		stream.Close()
		Return readLines
	End Function

/*	Static Function ReadAllLines( path As String, encoding As Encoding ) As Strings
		' TODO: 実装
	End Function */

	/*
	@brief  ファイルをすべて文字列として読み込む
	@param  ファイルパス
	@return ファイルの内容
	*/
	Static Function ReadAllText( path As String ) As String
		Dim stream = OpenText(path)
		Dim string = stream.ReadToEnd()
		stream.Close()
		Return string
	End Function

/*	Static Function ReadAllText( path As String, encoding As Encoding ) As String
		' TODO: 実装
	End Function */

	/*
	@brief  ファイルを置き換える
	@param  置き換えるファイルパス
	@param  置き換えられるファイルパス
	@param  置き換えられるファイルのバックアップを作成するファイルパス
	*/
	Static Sub Replace( sourceFileName As String, destinationFileName As String, destinationBackupFileName As String )
		Copy(destinationFileName, destinationBackupFileName)
		Copy(sourceFileName, destinationFileName, True)
	End Sub

/*	Static Sub Replace( sourceFileName As String, destinationFileName As String, destinationBackupFileName As String, ignoreMetadataErrors As Boolean )
		' TODO: 実装
	End Sub*/

/*	Static Sub SetAccessControl( path As String, fileSecurity As FileSecurity )
		' TODO: 実装
	End Sub */

	/*
	@brief  ファイルの属性を設定する
	@param  ファイルパス
	@param  ファイル属性
	*/
	Static Sub SetAttributes( path As String, fileAttributes As FileAttributes )
		If Not SetFileAttributes(ToTCStr(path), fileAttributes) Then
			Throw New IOException("File.SetAttributes: Failed to SetFileAttributes.")
		End If
	End Sub

	/*
	@brief  ファイルの作成日時を設定する
	@param  ファイルパス
	@param  作成日時
	*/
	Static Sub SetCreationTime( path As String, creationTime As DateTime )
		SetCreationTimeUtc(path, creationTime)
	End Sub

	/*
	@brief  ファイルの作成日時をUTC時刻で設定する
	@param  ファイルパス
	@param  作成日時
	*/
	Static Sub SetCreationTimeUtc( path As String, creationTimeUtc As DateTime )
		Dim hFile = createFileToSetTime(path) As HANDLE
		SetFileTime(hFile, creationTimeUtc.ToFileTimeUtc(), ByVal 0, ByVal 0)
		CloseHandle(hFile)
	End Sub

	/*
	@brief  ファイルの最終アクセス日時を設定する
	@param  ファイルパス
	@param  最終アクセス日時
	*/
	Static Sub SetLastAccessTime( path As String, lastAccessTime As DateTime )
		SetLastAccessTimeUtc(path, lastAccessTime)
	End Sub

	/*
	@brief  ファイルの最終アクセス日時をUTC時刻で設定する
	@param  ファイルパス
	@param  最終アクセス日時
	*/
	Static Sub SetLastAccessTimeUtc( path As String, lastAccessTimeUtc As DateTime )
		Dim hFile = createFileToSetTime(path) As HANDLE
		SetFileTime(hFile, ByVal 0, lastAccessTimeUtc.ToFileTimeUtc(), ByVal 0)
		CloseHandle(hFile)
	End Sub

	
	/*
	@brief  ファイルの最終書き込み日時を設定する
	@param  ファイルパス
	@param  最終書き込み日時
	*/
	Static Sub SetLastWriteTime( path As String, lastWriteTime As DateTime )
		SetLastWriteTimeUtc(path, lastWriteTime)
	End Sub

	/*
	@brief  ファイルの最終書き込み日時をUTC時刻で設定する
	@param  ファイルパス
	@param  最終書き込み日時
	*/
	Static Sub SetLastWriteTimeUtc( path As String, lastWriteTimeUtc As DateTime )
		Dim hFile = createFileToSetTime(path) As HANDLE
		SetFileTime(hFile, ByVal 0, ByVal 0, lastWriteTimeUtc.ToFileTimeUtc())
		CloseHandle(hFile)
	End Sub

/*	Static Sub WriteAllBytes( path As String, bytes As *Byte )
		' TODO: 実装
	End Sub*/

	/*
	@brief  リストに格納された文字列を一行ずつファイルに書き込む
	@param  ファイルパス
	@param  書き込む文字列リスト
	*/
	Static Sub WriteAllLines( path As String, contents As List<String> )
		Dim stream = New StreamWriter(path)
		Dim enumerator = contents.GetEnumerator()
		enumerator.Reset()
		While enumerator.MoveNext()
			stream.WriteLine(enumerator.Current)
		Wend
		stream.Close()
	End Sub

/*	Static Sub WriteAllLines( path As String, contents As Strings, encoding As Enconding )
		' TODO: 実装
	End Sub */

	/*
	@brief  ファイルに文字列を書き込む
	@param  ファイルパス
	@param  書き込む文字列
	*/
	Static Sub WriteAllText( path As String, contents As String )
		Dim stream = New StreamWriter(path)
		stream.Write(contents)
		stream.Close()
	End Sub

/*	Static Sub WriteAllText( path As String, contents As String, encoding As Enconding )
		' TODO: 実装
	End Sub */

Private
	'----------------------------------------------------------------
	' プライベート メソッド
	'----------------------------------------------------------------

	/*
	@brief  ファイルの情報を取得する
	@param  ファイルパス
	@return WIN32_FIND_DATA構造体
	*/
	Static Function getFileData(path As String) As WIN32_FIND_DATA
		Dim data As WIN32_FIND_DATA
		Dim hFind = FindFirstFile(ToTCStr(Path.GetFullPath(path)), data)
		FindClose(hFind)

		If hFind <> INVALID_HANDLE_VALUE Then
			Return data
		Else
			Throw New IOException("File.getFileData: Failed to FindFirstFile.")
		End If
	End Function

	/*
	@brief  ファイルの各種日時を変更するためのファイル作成を行う
	@param  ファイルパス
	@return ファイルハンドル
	*/
	Static Function createFileToSetTime(path As String) As HANDLE
		Dim hFile As HANDLE
		hFile = CreateFile(ToTCStr(path), GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, ByVal 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)
		If hFile = INVALID_HANDLE_VALUE Then
			CloseHandle(hFile)
			Throw New IOException("File.setFileTime: Failed to CreateFile.")
			Exit Function
		End If
		Return hFile
	End Function
End Class


End Namespace
End Namespace
