update_game = {}

update_game.app = sf.core.g_Application
update_game.options = s4.g_GameOptions.Instance().GetUpdateOptions()

update_game.strings = {}
update_game.strings[0] = sf.misc.g_StringTable.Instance().FormatByStringsID(_T("$558"))
update_game.strings[1] = sf.misc.g_StringTable.Instance().FormatByStringsID(_T("$559"))
update_game.strings[2] = _T("%d%% - %s/%s")

update_game.versions = _T("versions.xml.tmp")
update_game.files_info = _T("files_info.xml.tmp")

update_game.changed_files = nil
update_game.changed_files_count = 0
update_game.changed_files_i = 0

update_game.total_files_size = 0
update_game.downloaded_files_size = 0

update_game.url = update_game.app.GetSettings().GetChild(_T("settings"), false).GetValue(_T("url_update_game"))
update_game.branch = update_game.app.GetSettings().GetChild(_T("settings"), false).GetValue(_T("lang"))
update_game.update_semaphore = update_game.app.GetSettings().GetChild(_T("settings"), false).GetValue(_T("update_semaphore"))
update_game.flag_update = (update_game.app.GetSettings().GetChild(_T("settings"), false).GetValue(_T("update"))==_T("true"))

update_game.postfix = ""

update_game.on_child_action = {}

update_game.on_child_action.s4_update_suggest = function(_owner, _action, _child)

	if _action == _T("pressed") then
		
		if _child.GetId() == _T("update") then _owner.EndModal(0) end
		if _child.GetId() == _T("not_update") then _owner.EndModal(1) end
		if _child.GetId() == _T("later") then _owner.EndModal(2) end
		
	end

end

update_game.on_child_action.s4_update_check_files = function(_owner, _action, _child)

	if _child then
		if _child.GetId()==_T("cancel") and _action==_T("pressed") then
					
			__cast(_owner.GetWidget(_T("file_checker")), sf.gui.CBaseHTTPClient).Pause(true)	
			_owner.EndModal(download.enum.paused)

		elseif _child.GetId() == _T("file_checker") then
		
			local file_checker = __cast(_child, s4.CFileChecker)
			local state = file_checker.GetState()
		
			local stage_text = _T(string.format(T_(update_game.strings[0]).c_str(), 2, 3))
			local progress_text = _T(string.format(T_(update_game.strings[1]).c_str(), 100 * file_checker.GetProgress()))
			
			local label_stage = __cast(_owner.GetWidget(_T("label_stage")), sf.gui.CLabelWidget)
			local label_progress = __cast(_owner.GetWidget(_T("label_progress")), sf.gui.CLabelWidget)
			local progress_bar = __cast(_owner.GetWidget(_T("progress")), sf.gui.CProgressBarWidget)
			
			label_stage.SetText(stage_text)
			label_progress.SetText(progress_text)	
			progress_bar.SetValue(file_checker.GetProgress())
			
			_owner.UpdateLayout()
			
			if state == s4.CFileChecker.StateCheckingEnded then
				_owner.EndModal(download.enum.successful)
			end
			
		end
	end
end

update_game.on_child_action.s4_update_get_files = function(_owner, _action, _child)

	if _child then
		if _child.GetId()==_T("cancel") and _action==_T("pressed") then
					
			__cast(_owner.GetWidget(_T("http_client")), sf.gui.CBaseHTTPClient).Pause(true)	
			_owner.EndModal(download.enum.paused)

		elseif _child.GetId() == _T("http_client") then
		
			local http_client = __cast(_child, sf.gui.CBaseHTTPClient)
			local state = http_client.GetState()
			
			local stage_text = _T(string.format(T_(update_game.strings[0]).c_str(), 3, 3))
			
			local progress = 0.0
			local progress_text = _T("")
			
			if update_game.total_files_size ~= 0 then				
				local current_bytes = (update_game.downloaded_files_size + http_client.GetProgress()*update_game.changed_files.Get().Size)
				progress = (100 / update_game.total_files_size) * current_bytes
				progress_text = _T(string.format(T_(update_game.strings[2]).c_str(), progress, 
									download.size_get_string(current_bytes, update_game.postfix), 
									download.size_get_string(update_game.total_files_size, update_game.postfix)))
			else
				progress = (100 / update_game.changed_files_count) * (update_game.changed_files_i + http_client.GetProgress())
				progress_text = _T(string.format(T_(update_game.strings[1]).c_str(), progress))
			end
			
			local label_stage = __cast(_owner.GetWidget(_T("label_stage")), sf.gui.CLabelWidget)
			local label_progress = __cast(_owner.GetWidget(_T("label_progress")), sf.gui.CLabelWidget)
			local progress_bar = __cast(_owner.GetWidget(_T("progress")), sf.gui.CProgressBarWidget)
			
			label_stage.SetText(stage_text)
			label_progress.SetText(progress_text)			
			progress_bar.SetValue(progress/100.0)
			
			_owner.UpdateLayout()
			
			if state == sf.gui.CBaseHTTPClient.StateConnectingFailed then
			
				_owner.EndModal(download.enum.connection_failed)
			
			elseif state == sf.gui.CBaseHTTPClient.StateTransferringFailed then
			
				_owner.EndModal(download.enum.transfer_failed)
			
			elseif state == sf.gui.CBaseHTTPClient.StateTransferringSuccessful then
			
				update_game.downloaded_files_size = update_game.downloaded_files_size + update_game.changed_files.Get().Size
				
				update_game.changed_files.Next()
				update_game.changed_files_i = update_game.changed_files_i+1
				
				if not update_game.changed_files.IsEnd() then
					local file_info = update_game.changed_files.Get()
					local url = _T("")
					local dest = _T("")
										
					if file_info.Zip then
						url = update_game.url + _T("zip/") + file_info.Location + file_info.Name + _T(".zip")
						dest = sf.misc.AppendPath(_T("game"), file_info.Name) + _T(".zip") 
					else
						url = update_game.url + file_info.Location + file_info.Name
						dest = sf.misc.AppendPath(_T("game"), file_info.Name)
					end				
					
					http_client.Get(url, dest, true)
				else
					_owner.EndModal(download.enum.successful)
				end

			end
		end
	end
end

update_game.func_prepare_files_info = function(_owner)

	local stage_text = _T(string.format(T_(update_game.strings[0]).c_str(), 1, 3))
	local label_stage = __cast(_owner.GetWidget(_T("label_stage")), sf.gui.CLabelWidget)
	label_stage.SetText(stage_text)

end

update_game.doit = function(_owner)

	local opt = update_game.options
	
	opt.LastAttemptResult = s4.CGameOptions.UpdateOptions.RemindLater
	
	-------------------------------------------------------------------
	-- download files info
	-------------------------------------------------------------------
	local params_load_files_info = {}
	params_load_files_info.dialog_main = _T("s4_update_get_files_info")
	params_load_files_info.dialog_connection_error = _T("s4_update_connection")
	params_load_files_info.dialog_transfer_error = _T("s4_update_disconnect")
	params_load_files_info.dialog_cancel = _T("s4_update_cancel")
	params_load_files_info.url = update_game.url + _T("versions/") + update_game.branch + _T("/files.xml")
	params_load_files_info.outfile = update_game.files_info
	params_load_files_info.func_prepare_dialog_main = update_game.func_prepare_files_info
	
	local result_get_files_info = download.http_request(_owner, params_load_files_info)
	
	if result_get_files_info ~= download.enum.successful then return end

	-------------------------------------------------------------------
	-- compare files crc
	-------------------------------------------------------------------
	
	local dialog_file_checker = sf.gui.CWindow()
	game.load_window(_owner, dialog_file_checker, _T("s4_update_check_files"))
	local dialog_file_checker_ptr = sf.gui.CBaseWindowPtrT(dialog_file_checker)
	
	local file_checker = s4.CFileChecker(_T("file_checker"))
	local file_checker_ptr = sf.gui.CWidgetPtrT(file_checker)
	dialog_file_checker.AddWidget(file_checker_ptr)
	file_checker.Run(update_game.files_info)
	
	local file_check_result = download.enum.paused
	while file_check_result == download.enum.paused do
	
		file_check_result = _owner.DoModal(dialog_file_checker_ptr)		
		if file_check_result == download.enum.paused then

			local dialog_cancel = sf.gui.CWindow()
			game.load_window(_owner, dialog_cancel, _T("s4_update_cancel"))
			local dialog_cancel_ptr = sf.gui.CBaseWindowPtrT(dialog_cancel)
			
			if _owner.DoModal(dialog_cancel) == 1 then
				file_checker.Abort()
				file_checker_result = download.enum.cancelled
			else
				file_checker.Pause(false)
			end
		end
	end

	sf.misc.ShDeleteFile(update_game.files_info)
	
	if file_check_result ~= download.enum.successful then return end
	
	-------------------------------------------------------------------
	-- download files
	-------------------------------------------------------------------
	
	local params_load_files = {}
	params_load_files.dialog_main = _T("s4_update_get_files")
	params_load_files.dialog_connection_error = _T("s4_update_connection")
	params_load_files.dialog_transfer_error = _T("s4_update_disconnect")
	params_load_files.dialog_cancel = _T("s4_update_cancel")
	params_load_files.func_prepare_dialog_main = update_game.func_prepare_files_info
					
	update_game.changed_files = file_checker.GetChangedFiles()
	update_game.changed_files_count = file_checker.EnumChangedFiles()
	update_game.changed_files_i = 0
		
	update_game.total_files_size = 0
	while not update_game.changed_files.IsEnd() do
		update_game.total_files_size = update_game.total_files_size + update_game.changed_files.Get().Size
		update_game.changed_files.Next()
	end
	
	if update_game.total_files_size > 1024 then update_game.postfix="K" end
	if update_game.total_files_size > 1024*1024 then update_game.postfix="M" end
	
	update_game.downloaded_files_size = 0
	
	local load_files_result = download.enum.paused
	
	update_game.changed_files = file_checker.GetChangedFiles()
	if not update_game.changed_files.IsEnd() then
															
		local file_info = update_game.changed_files.Get()	
							
		if file_info.Zip then
			params_load_files.url = update_game.url + _T("zip/") + file_info.Location + file_info.Name + _T(".zip")
			params_load_files.outfile = sf.misc.AppendPath(_T("game"), file_info.Name) + _T(".zip") 
		else
			params_load_files.url = update_game.url + file_info.Location + file_info.Name
			params_load_files.outfile = sf.misc.AppendPath(_T("game"), file_info.Name)
		end
	
		load_files_result = download.http_request(_owner, params_load_files)
	
	end

	if load_files_result == download.enum.successful then
		
		sf.misc.WriteFile(sf.misc.AppendPath(_T("game"), update_game.update_semaphore), _T(""), false, false)	
		sf.misc.SetNamedFullAccess(_T("game"), true)
		update_game.restart_after_update(_owner, _T("s4_update_restart"))
		
	end	
end

update_game.run_check_update = function(_owner)

	print('abra4')
	io.flush()
	local url_versions = update_game.url + _T("versions/") + update_game.branch + _T("/versions.xml")
	local new_version_checker = s4.CNewVersionChecker(_T("new_version_checker"), url_versions, game.version)
	local new_version_checker_ptr = sf.gui.CWidgetPtrT(new_version_checker)
	_owner.AddWidget(new_version_checker_ptr)

end

update_game.suggest_update = function(_owner)
	
	local opt = update_game.options
	local dialog_suggest_id = _T("s4_update_y_version")
	
	if game.version.X < opt.VersionInfo.Version.X then dialog_suggest_id = _T("s4_update_x_version") end
	
	local dialog_suggest_update = sf.gui.CWindow()
	game.load_window(_owner, dialog_suggest_update, dialog_suggest_id)
	local dialog_suggest_update_ptr = sf.gui.CBaseWindowPtrT(dialog_suggest_update)
	
	local mod_res = _owner.DoModal(dialog_suggest_update_ptr)
	
	if mod_res == 1 then
	
		if opt.VersionInfo.CriticalChanges then 
			
			local dialog_critical_changes = sf.gui.CWindow()
			game.load_window(_owner, dialog_critical_changes, _T("s4_update_critical_version"))
			dialog_critical_changes_ptr = sf.gui.CBaseWindowPtrT(dialog_critical_changes)
			mod_res = _owner.DoModal(dialog_critical_changes_ptr)
		
		end
			
	end
	
	if mod_res == 0 then return 1 end
	
	if mod_res == 1 then
		opt.LastAttemptResult = s4.CGameOptions.UpdateOptions.Denied
	else
		opt.LastAttemptResult = s4.CGameOptions.UpdateOptions.RemindLater
	end
	
	return 0

end

update_game.try = function(_owner)

	local opt = update_game.options
	if opt.AvailableNewVersion and opt.LastAttemptResult ~= s4.CGameOptions.UpdateOptions.Denied then
		if update_game.suggest_update(_owner)==1 then
			update_game.doit(_owner)
		end
		return true
	end
	return false

end

update_game.restart_after_update = function(_owner, _dialog_id)

	local opt = update_game.options

	opt.AvailableNewVersion = false
	opt.LastAttemptResult = s4.CGameOptions.UpdateOptions.Allowed
	
	local settings = sf.core.CSettings()
	settings.LoadXml(sf.misc.AppendPath(sf.misc.AppendPath(_T("game"), _T("properties")), _T("version.xml")))
	local version_info = settings.GetChild(_T("version"), false)
	if not version_info.GetId().empty() then
		opt.VersionInfo.Version.X = tonumber(T_(version_info.GetValue(_T("x"))).c_str())
		opt.VersionInfo.Version.Y = tonumber(T_(version_info.GetValue(_T("y"))).c_str())
	end
	
	opt.VersionInfo.CriticalChanges = false
	
	local dialog_update_restart = sf.gui.CWindow()
	game.load_window(_owner, dialog_update_restart, _dialog_id)
	local dialog_update_restart_ptr = sf.gui.CBaseWindowPtrT(dialog_update_restart)
	
	if _owner.DoModal(dialog_update_restart_ptr) == 1 then
	
		local s4app = __cast(game.app, s4.CS4App)
		s4app.SetNeedRestart(true)
		game.app.Shutdown()
		
	end
end

update_game.check_update_try = function(window)

	print('abra1')
	io.flush()

	local opt = update_game.options
	local period = 60*60*24*7 --week
	
	if not game.is_correct_time(opt.LastAttemptTime) then
	
		print('abra2')
		io.flush()
		log("first start. check new version...")
		update_game.run_check_update(window)
					
	elseif os.time() - game.get_lua_time(opt.LastAttemptTime) >= period then

		print('abra3')
		io.flush()
		log("pass week. check new version...")
		update_game.run_check_update(window)
					
	end
end
