#include "window9.bi"

extern "C"
	declare function w9_strtok alias "strtok"(byval as zstring ptr, byval as const zstring ptr) as zstring ptr
End Extern

Type w9MAP_STRUCT
	As Zstring Ptr nKey
	As Any Ptr nData
	As w9MAP_STRUCT Ptr pLeft
	As w9MAP_STRUCT Ptr pRight
	As Byte bHeight
End Type

Type w9MAP_MAINSTRUCT
	As w9MAP_STRUCT Ptr pRoot
	As Byte bFlagDelete
	As Long iSizeMap
End Type

Dim Shared As HANDLE hSaveConfig

Dim Shared As USTRING sCurentGroup 

#ifdef __fb_win32__
	Private Function GetUtf8FromStr(s As USTRING) As String
		
		If Len(s) Then
			#ifdef UNICODE
				Return s.UTF8
			#else
				Dim As Wstring Ptr pwBuf = Asciitoutf(s)
				if pwBuf then
					Function = Unicodetoutf8(pwBuf)
					Deallocate(pwBuf)
				endif
			#endif
		Endif
		
	End Function
	
	Private Function GetStrFromUtf8(s As String) As USTRING
		
		If Len(s) Then
			#ifdef UNICODE
				Dim As USTRING us
				us.UTF8 = s 
				Return us
			#else
				Dim As Wstring Ptr pwBuf = Utf8tounicode(s)
				if pwBuf then
					Function = Utftoascii(pwBuf)
					Deallocate(pwBuf)
				endif
			#endif
		Endif
		
	End Function
	
	#ifdef UNICODE
		private Sub Write_StringN2 (ByVal H As HANDLE, ByRef String_ As USTRING)
			Dim iRetBytes As long
			Dim As Byte b,c
			b=13 : c=10
			dim as string sUtf8 = String_.UTF8
			If WriteFile(H,StrPtr(sUtf8),Len(sUtf8),@iRetBytes,0) Then
				If WriteFile(H,@b,1,@iRetBytes,0) Then
					WriteFile(H,@c,1,@iRetBytes,0)
				End If
			End If
		End Sub
	#endif
	
#endif

Private Sub w9InOrder(pRoot As w9MAP_STRUCT Ptr)  
	
	If pRoot <> 0 Then
		
		w9InOrder(pRoot->pLeft)
		
		If pRoot->nKey Andalso pRoot->nData Then
			
			Dim As USTRING usGroup , usKey , usVal
			
			Dim As Long iPos = Instr(*(pRoot->nKey) , "~!+!~")
			
			If iPos > 1 Then
				
				usGroup = Mid(*(pRoot->nKey) , 1 , iPos-1)
				
				usKey = Mid(*(pRoot->nKey) , iPos+5)
				
			Elseif iPos = 1 Then
				
				usKey = Mid(*(pRoot->nKey) , iPos+5)
				
			Endif
			
			#ifdef UNICODE
				Dim As Wstring Ptr pTemp = Cast(Wstring Ptr, pRoot->nData)
			#else
				Dim As Zstring Ptr pTemp = Cast(Zstring Ptr, pRoot->nData)
			#endif
			
			usVal = *pTemp
			
			If usVal = "~! !~" Then
				
				usVal = ""
				
			Endif
			
			dim as string sGroup , sKey , sVal
			
			#ifdef __fb_win32__
				#ifdef UNICODE
					sGroup = usGroup.UTF8
					sKey = usKey.UTF8
					sVal = usVal.UTF8
				#else
					sGroup = GetUtf8FromStr(usGroup)
					sKey = GetUtf8FromStr(usKey)
					sVal = GetUtf8FromStr(usVal)
				#EndIf
			#else
				sGroup = usGroup
				sKey = usKey
				sVal = usVal
			#EndIf
			
			If Len(sGroup) Then
				
				If sCurentGroup <> sGroup Then
					
					#ifdef __fb_win32__
						#ifdef UNICODE
							Write_stringn2(hSaveConfig , "[" & usGroup & "]")
							Write_stringn2(hSaveConfig , usKey & "=" & usVal)						
						#else	
							Write_stringn(hSaveConfig , "[" & sGroup & "]")
							Write_stringn(hSaveConfig , sKey & "=" & sVal)
						#EndIf
					#else
						Write_stringn(hSaveConfig , "[" & sGroup & "]")
						Write_stringn(hSaveConfig , sKey & "=" & sVal)
					#EndIf
					
					sCurentGroup = sGroup
					
				Else
					#ifdef __fb_win32__
						#ifdef UNICODE
							Write_stringn2(hSaveConfig , usKey & "=" & usVal)
						#else
							Write_stringn(hSaveConfig , sKey & "=" & sVal)
						#EndIf
					#else
						Write_stringn(hSaveConfig , sKey & "=" & sVal)
					#EndIf
				Endif
				
			Else
				
				#ifdef __fb_win32__
					#ifdef UNICODE
						Write_stringn2(hSaveConfig , usKey & "=" & usVal)
					#else
						Write_stringn(hSaveConfig , sKey & "=" & sVal)
					#EndIf
				#else
					Write_stringn(hSaveConfig , sKey & "=" & sVal)
				#EndIf
				
			Endif
			
		Endif
		
		w9InOrder(pRoot->pRight)
		
	Endif
	
End Sub

Function ConfigCreate() As Any Ptr
	
	Return CreateMap()
	
End Function

Sub ConfigDelete(p As Any Ptr)
	
	If p Then
		
		DeleteMap(p , 1)
		
	Endif
	
End Sub

Sub ConfigClear(p As Any Ptr)
	
	If p Then
		
		FreeMap(p , 1)
		
	Endif
	
End Sub

Sub ConfigDeleteValue(p As Any Ptr , sGroup As USTRING  , sKey As USTRING)
	
	If p Then
		
		FreeKeyMap(p , sGroup & "~!+!~" & sKey , 1)
		
	Endif
	
End Sub

Sub ConfigLoad(p As Any Ptr  , sPath As USTRING)
	
	Dim h As Handle
	
	Dim As Byte Ptr pData
	
	If p Andalso w9isFileExists(sPath) Then
		
		h = Read_file(sPath)
		
		If h <> Cast(Any Ptr, -1) Then
			
			pData = Read_datas(h , Size_file(h))
			
			If pData Then
				
				Dim As String sSep = Chr(13) & Chr(10)
				
				Dim As String sSepTrim = Chr(9) & " "
				
				Dim As String sGroup
				
				Dim As USTRING usGroup
				
				Dim As Zstring Ptr psz = w9_strtok(pData , Strptr(sSep))
				
				While (psz Andalso Len(*psz))
					
					If Left(*psz , 1) = "[" Then
						
						Dim As Long iPosE = Instr(2 , *psz , "]")
						
						If iPosE Then
							
							sGroup = Trim(Mid(*psz , 2 , iPosE - 2) , Any Chr(9) & " ")
							
							#ifdef __fb_win32__
								usGroup = GetStrFromUtf8(sGroup)
							#else
								usGroup = sGroup
							#endif
							
						Endif
						
					Else
						
						Dim As String s1 , s2
						
						Dim As USTRING usKey , usVal
						
						Dim As Long iPos = Instr(*psz , "=")
						
						If iPos>1 Then
							
							s1 = Trim(Mid(*psz , 1 , iPos-1) , sSepTrim)
							
							s2 = Mid(*psz , iPos+1)
							
							#ifdef __fb_win32__
								usKey = GetStrFromUtf8(s1)
								usVal = GetStrFromUtf8(s2)
							#else
								usKey = s1
								usVal = s2
							#endif
							
						Endif
						
						If Len(usGroup) Andalso Len(usKey) Then
							
							If Len(usVal) Then
								
								SetValueStrMap(p , usGroup & "~!+!~" & usKey , usVal)
								
							Else
								
								SetValueStrMap(p , usGroup & "~!+!~" & usKey , "~! !~")
								
							Endif
							
						Elseif Len(usKey) Then
							
							If Len(usVal) Then
								
								SetValueStrMap(p , "~!+!~" & usKey , usVal)
								
							Else
								
								SetValueStrMap(p , "~!+!~" & usKey , "~! !~")
								
							Endif
							
						Endif
						
					Endif
					
					psz = w9_strtok(0 , Strptr(sSep))
					
				Wend
				
				Deallocate(pData)
				
			Endif
			
			Close_file(h)
			
		Endif
		
	Endif
	
End Sub

Sub ConfigSave(p As Any Ptr  , sPath As USTRING)
	
	If p = 0 Then Exit Sub
	
	hSaveConfig = Create_file(sPath)
	
	If hSaveConfig <> Cast(Any Ptr, -1) Then
		
		w9InOrder(Cast(w9MAP_MAINSTRUCT Ptr , p)->pRoot)
		
		Close_file(hSaveConfig)
		
		sCurentGroup = ""
		
	Endif
	
End Sub

Sub SetConfigValue(p As Any Ptr  , sGroup As USTRING , sKey As USTRING , sValue As USTRING)
	
	If p Then
		
		If Len(sValue) Then
			
			SetValueStrMap(p , sGroup & "~!+!~" & sKey , sValue)
			
		Else
			
			SetValueStrMap(p , sGroup & "~!+!~" & sKey , "~! !~")
			
		Endif
		
	Endif
	
End Sub

Function GetConfigValue(p As Any Ptr  , sGroup As USTRING , sKey As USTRING) As USTRING
	
	If p Then
		
		Dim As USTRING us = GetValueStrMap(p , sGroup & "~!+!~" & sKey)
		
		If us <> "~! !~" Then
			
			Return us
			
		Endif
		
	Endif
	
End Function