﻿#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=edit-copy-3.ico
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <File.au3>
#include <GuiStatusBar.au3>
#include <ProgressConstants.au3>
#include <WinAPIError.au3>
#include <WinAPIFiles.au3>
#include "GroupEx.au3"

Opt('TrayAutoPause', 0)
OnAutoItExitRegister('_Exit')

; callback für progress
; https://docs.microsoft.com/en-us/windows/win32/api/winbase/nc-winbase-lpprogress_routine
Global $hProgressProc = DllCallbackRegister('_ProgressProc', 'bool', 'uint64;uint64;uint64;uint64;dword;dword;handle;handle;ptr')

Global $INI = _ScriptNameINI(False)
If Not FileExists($INI) Then Exit MsgBox(16, 'FEHLER', 'Die Datei ' & @CRLF & '"' & $INI & '"' & @CRLF & 'ist nicht im Programmordner!')

#cs INI

[copy]

; vom Server zum USB-Stick
source_pc=\\Server\GDILine\Factur
; target_usb=Root_dieses_USB-Sticks, automatische Erkennung im Programm

; vom USB-Stick zum Virtual-PC
; source_usb=Root_dieses_USB-Sticks, automatische Erkennung im Programm
target_vmshare=C:\VM_Share

#ce

Global $sourcePC = IniRead($INI, 'copy', 'source_pc', '\\Server\GDILine\Factur')
Global $targetUSB = StringLeft(@ScriptDir, 3)

Global $sourceUSB = $targetUSB
Global $targetVM = IniRead($INI, 'copy', 'target_vmshare', 'C:\VM_Share')

Global $sTitle = 'GDI.GDB - CopyTool'
Global $hGui = GUICreate($sTitle, 600, 175)
GUISetBkColor(0xFFFFFF)
Global $tGroup = _GuiCtrlGroup_Create($hGui, 'Kopieren Datenbank Datei', 15, 15, 570, 125, 0x000080, 0x33A644, -1, BitOR($_GROUPTEXT_RIGHT, $_GROUPTEXT_ITALIC))
GUICtrlCreateLabel('Bitte den Kopiervorgang auswählen!', 25, 30)
Global $rPC2USB = GUICtrlCreateRadio(' Kopiere vom PC auf USB-Stick', 25, 50)
GUICtrlSetState(-1, $GUI_CHECKED)
Global $rUSB2Share = GUICtrlCreateRadio(' Kopiere vom USB-Stick auf Share des Virtual-PC', 25, 75)
Global $btRun = GUICtrlCreateButton('Starte Kopiervorgang', 390, 70, 185, 25)
Global $lbComplete = GUICtrlCreateLabel('', 25, 105, 550, 20) ;  ERFOLG
GUICtrlSetColor(-1, 0x0000FF)

Global $hStatus = _GUICtrlStatusBar_Create ($hGUI)
_GUICtrlStatusBar_SetMinHeight($hStatus, 20)
Global $idProgress = GUICtrlCreateProgress(0, 0, -1, -1, $PBS_SMOOTH)
GUICtrlSetColor(-1, 0x008B00) ; grün
_GUICtrlStatusBar_EmbedControl($hStatus, 0, GUICtrlGetHandle($idProgress))


GUISetState(@SW_SHOW)


Global $tFile, $source, $target

While True
	Switch GUIGetMsg()
		Case -3
			Exit
		Case $btRun
			If BitAND(GUICtrlRead($rPC2USB), $GUI_CHECKED) Then
				$source = $sourcePC
				$target = $targetUSB
			Else
				$source = $sourceUSB
				$target = $targetVM
			EndIf
			$tFile = _GDInewestFile($source)
			If @error Then
				MsgBox(16, 'FEHLER', $tFile)
			Else
				GUICtrlSetState($btRun, $GUI_DISABLE)
				GUICtrlSetData($lbComplete, 'Kopiere: GDI.GDB vom "' & $tFile.Date & '"')
				_Copy_w_Progress($tFile.Path & $tFile.File, StringRegExpReplace($target, '(\\)*$', '') & '\' & $tFile.File)
			EndIf

	EndSwitch
WEnd


Func _Copy_w_Progress($_source, $_destination)
	If Not _WinAPI_CopyFileEx($_source, $_destination, 0, DllCallbackGetPtr($hProgressProc)) Then
		_WinAPI_ShowLastError('Beim Kopieren der Datei "' & $_source & '" ist ein Fehler aufgetreten.')
		_ProgressSetData()
		WinSetTitle($hGUI, '', $sTitle)
		GUICtrlSetData($lbComplete, '')
		GUICtrlSetState($btRun, $GUI_ENABLE)
	EndIf
EndFunc

Volatile Func _ProgressProc($iTotalFileSize, $iTotalBytesTransferred, $iStreamSize, $iStreamBytesTransferred, $iStreamNumber, $iCallbackReason, $hSourceFile, $hDestinationFile, $pData)
	#forceref $iStreamSize, $iStreamBytesTransferred, $iStreamNumber, $iCallbackReason, $hSourceFile, $hDestinationFile, $pData
	Local $iPercent = Round($iTotalBytesTransferred / $iTotalFileSize * 100)
	_ProgressSetData($iPercent, $iTotalBytesTransferred, $iTotalFileSize, $lbComplete)
	Sleep(10)
	Return $PROGRESS_CONTINUE
EndFunc


Func _ProgressSetData($_i=-1, $_BytesTrans=0, $_BytesTotal=0, $_idMsg=Null)
	GUICtrlSetData($idProgress, ($_i = -1 ? 0 : $_i))
	Local $sPercent
	Switch $_i
		Case 100
			$sPercent = '     [ Vollständig ]'
			If $_idMsg <> Null Then GUICtrlSetData($_idMsg, 'Kopiervorgang abgeschlossen.')
			AdlibRegister('_ResetProgess', 750)
		Case -1
			$sPercent = ''
		Case Else
			$sPercent = StringFormat('     [ %s von %s - %d %% ]', _FormatByte($_BytesTrans, 'MB', False, 1), _FormatByte($_BytesTotal, 'MB', False, 1), $_i)
	EndSwitch
	WinSetTitle($hGUI, '', StringFormat('%s%s', $sTitle, $sPercent) )
EndFunc


Func _ResetProgess()
	AdlibUnRegister('_ResetProgess')
	_ProgressSetData()
	GUICtrlSetState($btRun, $GUI_ENABLE)
EndFunc


Func _Exit()
	DllCallbackFree($hProgressProc)
EndFunc


Func _ScriptNameINI($_bFileOnly=True)
	Local $sRepl = $_bFileOnly ? '\1.ini' : '\\\1.ini'
	Return ($_bFileOnly ? '' : @ScriptDir) & StringRegExpReplace(@ScriptName, '(.+)(\.[^\.]+)$', $sRepl)
EndFunc


; ermittelt im $_Source-Ordner die neueste Datei "GDI_ORIG_JJJJ_MM_TT.GDB"
Func _GDInewestFile($_Source)
	$_Source = StringRegExpReplace($_Source, '(\\)*$', '') & '\'
	; existiert Ordner
	If Not FileExists($_Source) Then Return SetError(1,0,'"' & $_Source & '" existiert nicht!')
	; alle vorhandenen GDB-Dateien auflisten
	Local $aSource = _FileListToArray($_Source, 'gdi*.gdb', 1)
	If @error Then Return SetError(2,0,'Es wurden keine "GDI*.GDB" - Dateien gefunden in: "' & $_Source & '" !')

	; Filtern nach jüngster Datei "GDI_ORIG_JJJJ_MM_TT.GDB"
	Local $sDate = '2000_01_01'
	Local $aMatch, $aDate
	For $i = 1 To $aSource[0]
		$aMatch =StringRegExp($aSource[$i], 'GDI_ORIG_(\d{4}_\d{2}_\d{2})\.GDB', 1)
		If IsArray($aMatch) Then
			If $aMatch[0] > $sDate Then $sDate = $aMatch[0]
		EndIf
	Next
	If $sDate = '2000_01_01' Then Return SetError(3,0,'Keine gefundene Datei entspricht dem Muster: "GDI_ORIG_JJJJ_MM_TT.GDB" !')
	$sNewDate = StringRegExpReplace($sDate, '(\d{4})_(\d{2})_(\d{2})', '\3.\2.\1')
	Local $FileNewest = 'GDI_ORIG_' & $sDate & '.GDB'
	Local $tResult = DllStructCreate('char Path[' & StringLen($_Source) & '];char File[' & StringLen($FileNewest) & ']; char Date[' & StringLen($sNewDate) & ']')
	$tResult.Path = $_Source
	$tResult.File = $FileNewest
	$tResult.Date = $sNewDate
	Return $tResult
EndFunc

; #FUNCTION# ====================================================================================================================
; Name ..........: _FormatByte
; Description ...: Formats a given value of bytes with highest or given unit, optional as structure with all units
; Parameters ....: $_iByte    The value of bytes to format
; ...............: $_sUnit    (Default = '', unit of highest value) or count of given unit (TB, GB, MB, KB, Byte)
; ...............: $_fStruct  Returns a structure with .TB .GB .MB .KB .Byte (Default = False)
; ...............: $_sDigit   Number of decimal digits (Default = '3') as string!
; Return values .: The formatted string or the structure.
; Author ........: BugFix
; ===============================================================================================================================
Func _FormatByte($_iByte, $_sUnit='', $_fStruct=False, $_sDigit='3')
	Local Static $aByte[5][2] = [[0x10000000000],[0x40000000],[0x100000],[0x400],[0x1]]
	Local Static $tBytes = DllStructCreate('int TB;int GB;int MB;int KB;int Byte;')
	Local Static $aUnit[5] = ['TB','GB','MB','KB','Byte']
	Local $iModulo = $_iByte, $iHighest = 4
	For $i = 0 To 3
		$aByte[$i][1] = $iModulo >= $aByte[$i][0] ? Floor($iModulo/$aByte[$i][0]) : 0
		$iModulo = $aByte[$i][1] > 0 ? Mod($iModulo,$aByte[$i][0]) : $iModulo
		$iHighest = $aByte[$i][1] > 0 ? ($i < $iHighest ? $i : $iHighest) : $iHighest
	Next
	$aByte[4][1] = $iModulo
	If $_fStruct Then
		$tBytes.TB   = $aByte[0][1]
		$tBytes.GB   = $aByte[1][1]
		$tBytes.MB   = $aByte[2][1]
		$tBytes.KB   = $aByte[3][1]
		$tBytes.Byte = $aByte[4][1]
		Return $tBytes
	EndIf
	$_sUnit = StringInStr('TB GB MB KB Byte', $_sUnit) ? $_sUnit : ''
	$_sUnit = $_sUnit = '' ? $aUnit[$iHighest] : $_sUnit
	Local $iUserUnit = Floor(StringInStr('TB GB MB KB Byte', $_sUnit)/3)
	If Number($_sDigit) < 0 Then $_sDigit = '0'
	Local $sFormat = '%.' & $_sDigit & 'f %s'
	Return StringFormat($sFormat, $_iByte/$aByte[$iUserUnit][0], $aUnit[$iUserUnit])
EndFunc  ;==>_FormatByte