#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_icon=download.ico
#AutoIt3Wrapper_Res_Comment=LAME/FAAC Downloader
#AutoIt3Wrapper_Res_Language=1033
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#cs
Icon: http://www.iconfinder.com/icondetails/27806/64/arrow_bottom_download_icon
#ce

#cs
 (c) 2011, oov

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
 met:

     * Redistributions of source code must retain the above copyright
 notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above
 copyright notice, this list of conditions and the following disclaimer
 in the documentation and/or other materials provided with the
 distribution.
     * Neither the name of oov nor the names of its
 contributors may be used to endorse or promote products derived from
 this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ce
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <ProgressConstants.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>
#include "Zip.au3" ;from http://www.autoitscript.com/forum/topic/73425-zip-au3-udf-in-pure-autoit/

Global Const $DEBUGGING = False

Global Const $LFERR_OK = 0
Global Const $LFERR_CANCEL = 1
Global Const $LFERR_HTTP_ERROR = 2
Global Const $LFERR_HTML_PARSE_ERROR = 3
Global Const $LFERR_FILE_NOT_FOUND_IN_ZIP = 4
Global Const $LFERR_ZIP_READ_ERROR = 5
Global Const $LFERR_FILE_COPY_ERROR = 6

Local Const $LAME_DIR = @ScriptDir
Local Const $LAME_DLL_FILENAME = "lame_enc.dll"
Local Const $LAME_INI_FILENAME = "lame_enc.ini"
Local Const $LAME_HTML_DOWNLOAD_URL = "http://www.rarewares.org/mp3-lame-libraries.php"
Local Const $LAME_TEMP_HTML_DOWNLOAD_PATH = @TempDir & "\temporary_lame.html"
Local Const $LAME_TEMP_ZIP_DOWNLOAD_PATH = @TempDir & "\temporary_lame.zip"

Local Const $FAAC_DIR = @ScriptDir
Local Const $FAAC_DLL_FILENAME = "libfaac.dll"
Local Const $FAAC_HTML_DOWNLOAD_URL = "http://www.rarewares.org/aac-encoders.php"
Local Const $FAAC_TEMP_HTML_DOWNLOAD_PATH = @TempDir & "\temporary_faac.html"
Local Const $FAAC_TEMP_ZIP_DOWNLOAD_PATH = @TempDir & "\temporary_faac.zip"

AutoItSetOption("MustDeclareVars", 1)
Opt("GUIOnEventMode", 1)

Local $LFDownloadDialog, $ProgressBar, $Description, $CancelButton, $Cancelled

Main()
Func Main($Title = "LAME/FAAC Downloader", $CancelCaption = "Cancel")
	If _HasLameFaac() Then
		MsgBox(0, $Title, "LAME/FAAC were already installed.")
		Return True
	EndIf

	#Region ### START Koda GUI section ### Form=
	$LFDownloadDialog = GUICreate($Title, 274, 91, -1, -1)
	$ProgressBar = GUICtrlCreateProgress(8, 24, 254, 17, $PBS_SMOOTH)
	$Description = GUICtrlCreateLabel("", 8, 8, 254, 16)
	$CancelButton = GUICtrlCreateButton($CancelCaption, 192, 56, 75, 25, BitOR($BS_DEFPUSHBUTTON, $WS_GROUP))
	GUICtrlSetOnEvent(-1, "__CancelButtonClick")
	GUISetState(@SW_SHOW)
	#EndRegion ### END Koda GUI section ###

	If Not __RemoveLameFaacTempFiles() Then Return False

	$Cancelled = False
	ControlSetText($LFDownloadDialog, "", $Description, "")
	GUICtrlSetData($ProgressBar, 0)

	If Not _HasLame() And MsgBox(4 + 32, $Title, "Do you want to install LAME from Rarewares?", 0, $LFDownloadDialog) == 6 Then
		__SetupLame()
		Switch @error
			Case $LFERR_OK
				MsgBox(64, $Title, "LAME installed.", 0, $LFDownloadDialog)
			Case $LFERR_CANCEL
				MsgBox(64, $Title, "LAME installation cancelled.", 0, $LFDownloadDialog)
			Case Else
				MsgBox(16, $Title, "Could not be installed LAME because an error occurred." & @CRLF & "REASON: " & _LFErrorCodeToMessage(@error), 0, $LFDownloadDialog)
		EndSwitch
	EndIf

	$Cancelled = False
	ControlSetText($LFDownloadDialog, "", $Description, "")
	GUICtrlSetData($ProgressBar, 0)

	If Not _HasFaac() And MsgBox(4 + 32, $Title, "Do you want to install FAAC from Rarewares?", 0, $LFDownloadDialog) == 6 Then
		__SetupFaac()
		Switch @error
			Case $LFERR_OK
				MsgBox(64, $Title, "FAAC installed.", 0, $LFDownloadDialog)
			Case $LFERR_CANCEL
				MsgBox(64, $Title, "FAAC installation cancelled.", 0, $LFDownloadDialog)
			Case Else
				MsgBox(16, $Title, "Could not be installed FAAC because an error occurred." & @CRLF & "REASON: " & _LFErrorCodeToMessage(@error), 0, $LFDownloadDialog)
		EndSwitch
	EndIf

	GUIDelete($LFDownloadDialog)
	Return True
EndFunc   ;==>Main

Func _HasLameFaac()
	Return SetError($LFERR_OK, 0, _HasLame() And _HasFaac())
EndFunc   ;==>_HasLameFaac

Func _HasLame()
	Return SetError($LFERR_OK, 0, FileExists($LAME_DIR & '\' & $LAME_DLL_FILENAME))
EndFunc   ;==>_HasLame

Func _HasFaac()
	Return SetError($LFERR_OK, 0, FileExists($FAAC_DIR & '\' & $FAAC_DLL_FILENAME))
EndFunc   ;==>_HasFaac

Func _LFErrorCodeToMessage($errorCode)
	Switch $errorCode
		Case $LFERR_OK
			Return "Successful"
		Case $LFERR_CANCEL
			Return "Cancelled"
		Case $LFERR_HTTP_ERROR
			Return "Download error"
		Case $LFERR_HTML_PARSE_ERROR
			Return "HTML parse error"
		Case $LFERR_FILE_NOT_FOUND_IN_ZIP
			Return "File not found in zip"
		Case $LFERR_ZIP_READ_ERROR
			Return "Zip read error"
		Case $LFERR_FILE_COPY_ERROR
			Return "Could not copy file"
		Case Else
			Return "Unknown error"
	EndSwitch
EndFunc   ;==>_LFErrorCodeToMessage

#Region Internal Function

Func __SetupLame()
	ControlEnable($LFDownloadDialog, "", $CancelButton)

	ControlSetText($LFDownloadDialog, "", $Description, "Now finding download URI...")
	If Not __DownloadFile($LAME_HTML_DOWNLOAD_URL, $LAME_TEMP_HTML_DOWNLOAD_PATH, $ProgressBar) Then Return False

	Local $ZipUri = __ParseLameHTML()
	If @error Then Return False

	ControlSetText($LFDownloadDialog, "", $Description, "Now Downloading...")
	If Not __DownloadFile($ZipUri, $LAME_TEMP_ZIP_DOWNLOAD_PATH, $ProgressBar) Then Return False

	ControlDisable($LFDownloadDialog, "", $CancelButton)

	ControlSetText($LFDownloadDialog, "", $Description, "Now Extracting...")
	If Not __ExtractLameZip() Then Return False

	Return SetError($LFERR_OK, 0, True)
EndFunc   ;==>__SetupLame

Func __ParseLameHTML()
	Local $s = BinaryToString(FileRead($LAME_TEMP_HTML_DOWNLOAD_PATH), 4)
	$s = StringRegExpReplace($s, '\r\n|\r|\n|\t', ' ')
	$s = StringRegExpReplace($s, '^.*"lame_dll_ini".*?</h3>', '')
	$s = StringRegExpReplace($s, '</a>.*$', '')
	Return __GetURLFromString($s)
EndFunc   ;==>__ParseLameHTML

Func __ExtractLameZip()
	If Not __ExtractFileFromZip($LAME_TEMP_ZIP_DOWNLOAD_PATH, $LAME_DLL_FILENAME, $LAME_DIR) Then Return False

	If Not FileExists($LAME_DIR & '\' & $LAME_INI_FILENAME) Then
		__ExtractFileFromZip($LAME_TEMP_ZIP_DOWNLOAD_PATH, $LAME_INI_FILENAME, $LAME_DIR)
	EndIf
	Return SetError($LFERR_OK, 0, True)
EndFunc   ;==>__ExtractLameZip

Func __SetupFaac()
	ControlEnable($LFDownloadDialog, "", $CancelButton)

	ControlSetText($LFDownloadDialog, "", $Description, "Now finding FAAC download...")
	If Not __DownloadFile($FAAC_HTML_DOWNLOAD_URL, $FAAC_TEMP_HTML_DOWNLOAD_PATH, $ProgressBar) Then Return False

	Local $ZipUri = __ParseFaacHTML()
	If @error Then Return False

	ControlSetText($LFDownloadDialog, "", $Description, "Now Downloading...")
	If Not __DownloadFile($ZipUri, $FAAC_TEMP_ZIP_DOWNLOAD_PATH, $ProgressBar) Then Return False

	ControlDisable($LFDownloadDialog, "", $CancelButton)

	ControlSetText($LFDownloadDialog, "", $Description, "Now Extracting...")
	If Not __ExtractFaacZip() Then Return False

	Return SetError($LFERR_OK, 0, True)
EndFunc   ;==>__SetupFaac

Func __ParseFaacHTML()
	Local $s = BinaryToString(FileRead($FAAC_TEMP_HTML_DOWNLOAD_PATH), 4)
	$s = StringRegExpReplace($s, '\r\n|\r|\n|\t', ' ')
	$s = StringRegExpReplace($s, '^.*"libfaac-win".*?</h3>', '')
	$s = StringRegExpReplace($s, '</a>.*$', '')
	Return __GetURLFromString($s)
EndFunc   ;==>__ParseFaacHTML

Func __ExtractFaacZip()
	If Not __ExtractFileFromZip($FAAC_TEMP_ZIP_DOWNLOAD_PATH, $FAAC_DLL_FILENAME, $FAAC_DIR) Then Return False
	Return SetError($LFERR_OK, 0, True)
EndFunc   ;==>__ExtractFaacZip

Func __CancelButtonClick()
	$Cancelled = True
	ControlDisable($LFDownloadDialog, "", $CancelButton)
EndFunc   ;==>__CancelButtonClick

Func __DownloadFile($uri, $file, $ProgressBar = 0)
	If Not (FileExists($file)) Then
		Local $h = InetGet($uri, $file, 1, 1), $total, $read
		Do
			Sleep(50)
			$total = InetGetInfo($h, 1)
			$read = InetGetInfo($h, 0)
			If $total And $read And $ProgressBar Then GUICtrlSetData($ProgressBar, ($read / $total) * 100)
		Until InetGetInfo($h, 2) Or $Cancelled
		Local $downloadSuccessful = InetGetInfo($h, 3)
		InetClose($h)

		If $ProgressBar Then GUICtrlSetData($ProgressBar, 100)

		If $Cancelled Then Return SetError($LFERR_CANCEL, 0, False)
		If Not $downloadSuccessful Then Return SetError($LFERR_HTTP_ERROR, 0, False)
	EndIf
	Return SetError($LFERR_OK, 0, True)
EndFunc   ;==>__DownloadFile

Func __GetURLFromString($s)
	Local $ret = StringRegExp($s, '(https?|ftp)(://[-_.!~*''()a-zA-Z0-9;\/?:\@&=+\$,%#]+)', 2)
	If @error Then Return SetError($LFERR_HTML_PARSE_ERROR, 0, "")
	Return SetError($LFERR_OK, 0, $ret[0])
EndFunc   ;==>__GetURLFromString

Func __ExtractFileFromZip($zip, $file, $dir)
	If Not _Zip_ItemExists($zip, $file) Then Return SetError($LFERR_FILE_NOT_FOUND_IN_ZIP, 0, False)
	If Not _Zip_Unzip($zip, $file, $dir, BitOR(1, 4, 16, 512, 1024)) Then Return SetError($LFERR_ZIP_READ_ERROR, 0, False)
	Return SetError($LFERR_OK, 0, True)
EndFunc   ;==>__ExtractFileFromZip

#OnAutoItStartRegister "SetupLameFaacStartup"
Func SetupLameFaacStartup()
	OnAutoItExitRegister("__RemoveLameFaacTempFiles")
EndFunc   ;==>SetupLameFaacStartup

Func __RemoveLameFaacTempFiles()
	If Not $DEBUGGING Then
		FileDelete($LAME_TEMP_HTML_DOWNLOAD_PATH)
		FileDelete($LAME_TEMP_ZIP_DOWNLOAD_PATH)
		FileDelete($FAAC_TEMP_HTML_DOWNLOAD_PATH)
		FileDelete($FAAC_TEMP_ZIP_DOWNLOAD_PATH)
	EndIf

	If $Cancelled Then Return SetError($LFERR_CANCEL, 0, False)
	Return SetError($LFERR_OK, 0, True)
EndFunc   ;==>__RemoveLameFaacTempFiles

#EndRegion Internal Function