#! ruby -Ku
#-----------------------------------------------------------
# DarkHall Auto Updater
#
# Author:   Team D.H. <team.darkhall@gmail.com>
# License:  NYSL 0.9982 <http://www.kmonos.net/nysl/>
#           (unlike other files)
# URL:      http://wiz.morphball.net/darkhall/
#-----------------------------------------------------------

require './bootstrap'

require 'open-uri'
require 'locale'
require 'gettext'
require 'zlib'
require 'archive/tar/minitar'
require 'anjson'

require 'darkhall/const'

require 'wx'
require 'wxconstructor'

if $LOADED_FEATURES.include?('exerb/mkexy.rb') or defined?(ExerbRuntime) then
	require '__wxautoload'
end

ROOT_PATH = Pathname.new(__FILE__).dirname
puts "root_dir: #{ROOT_PATH.to_s}"



module Updater
	def self.run_on_thread(&proc)
		Thread.abort_on_exception = true
		thread = Thread.new{
			begin
				proc.call
			rescue Exception
				log_path = ROOT_PATH + 'operation_error.log'
				open(log_path, 'w'){|f|
					f.puts $!.to_s
					f.puts $!.backtrace
				}
				Kernel.raise $!
			end
		}
		timer = Wx::Timer.every(1) do
			Thread.pass
		end
		
		return thread
	end


	class App < Wx::App
		include GetText
		def on_init
			@dialog = Dialog.new(nil, :title => _('DarkHall 自動バージョンアップ'))
			@dialog.show_modal
		end
	end
	
	class Dialog < Wx::Dialog
		include GetText
		def initialize(*args)
			super
			self.window_style |= Wx::STAY_ON_TOP
			centre

			topsz = nil
			dialog = self
			construct_children do
				widget Wx::Panel do
					topsz = vbox_sizer do
						expand
						border 8
						widget Wx::StaticText, :label => '新バージョンを確認中...', :name => 'state'
						
						widget Wx::Gauge, :style => Wx::GA_HORIZONTAL|Wx::GA_SMOOTH, :range => 100, :name => 'download_gauge'
						widget Wx::Gauge, :style => Wx::GA_HORIZONTAL|Wx::GA_SMOOTH, :range => 100, :name => 'unpack_gauge'
						
						hbox_sizer do
							stretch_spacer 1
							proportion 1
							but = widget Wx::Button, :label => 'バージョンアップ実行', :name => 'decide_button'
							but.set_default
							but.disable
							dialog.evt_button(but, :on_update)
							stretch_spacer 1
						end
					end
				end
			end
			
			topsz.fit(self)
			evt_close(:on_cancel)
			evt_show(self, :on_show)
		end
		
		def on_show
			Updater.run_on_thread do
				uri = URI("http://wiz.morphball.net/darkhall/beta-update.cgi")
				begin
					input = uri.open
					data = AnJSON.parse(input.read)
					
					state = find_window_by_name('state')
					if data['latest_version'] > DarkHall::VERSION_CODE then
						@download_uri = URI(data['download_uri'])
						state.label = "#{data['latest_version_name']} が入手可能です。"
						find_window_by_name('decide_button').enable
					else
						state.label = "すでに最新のβ版がインストールされています。"
					end
				rescue OpenURI::HTTPError
					find_window_by_name('state').label = "新バージョンの確認に失敗しました。 (#{$!.to_s})"
				end
			end
		end
		
		def on_update
			state = find_window_by_name('state')
			download_gauge = find_window_by_name('download_gauge')
			unpack_gauge = find_window_by_name('unpack_gauge')
			
			on_content_length = proc do |len|
				download_gauge.range = len
			end
			on_progress = proc do |got|
				download_gauge.value = got
				state.label = "ダウンロード中... (#{(got * 100 / download_gauge.range).to_i}%)"
			end
			
			Updater.run_on_thread do
				begin
					@download_uri.open(:progress_proc => on_progress, :content_length_proc => on_content_length){|input|
						download_gauge.value = download_gauge.range
						tgz = Zlib::GzipReader.new(input)
						dest = ROOT_PATH + 'tgz_out/'
						
						unpack_gauge.range = input.size
						Archive::Tar::Minitar.unpack(tgz, dest.to_s) do |event_type, entry_name, stats|
							case event_type
							when :file_start, :file_progress, :file_done
								unpack_gauge.value = input.pos
								state.label = "バージョンアップ中... (#{(input.pos * 100 / unpack_gauge.range).to_i}%)"
							end
						end
						unpack_gauge.value = unpack_gauge.range
					}
					state.label = "完了しました。"
					find_window_by_name('decide_button').disable
				rescue OpenURI::HTTPError
					state.label = "新バージョンのダウンロードに失敗しました。 (#{$!.to_s})"
				end
			end
				
			#exit
		end
		
		def on_cancel
			exit
		end
	end
end

app = Updater::App.new
unless $LOADED_FEATURES.include?('exerb/mkexy.rb') then
	app.main_loop
end

