# encoding: utf-8
#-----------------------------------------------------------
# DarkHall rakefile (for windows)
#
# Requirement:
#   Exerb, RSpec, Info-Zip,
#   msvcr71.dll, msvcp71.dll,
#   DarkHall resource package
#     <http://wiz.morphball.net/darkhall/build-guide.html>
#-----------------------------------------------------------
require './bootstrap'

require 'yaml'
require 'rake/clean'
require 'rubyplus'

require 'digest/md5'
require 'fileutils'
require 'spec/rake/spectask'
require 'msgpack'

	
ver = ENV['DHVER'] || 'b00'
PACKAGE_NAME = "darkhall-#{ver}.zip"
PATCH_PACKAGE_NAME = "darkhall-#{ver}_patch.zip"
LINUX_PACKAGE_NAME = "darkhall-#{ver}_linux.zip"
LINUX_PATCH_PACKAGE_NAME = "darkhall-#{ver}_linux_patch.zip"
SRC_PACKAGE_NAME = "darkhall-#{ver}_src.zip"
RES_PACKAGE_NAME = "darkhall-#{ver}_res.zip"
LANG_PACKAGE_NAME = "darkhall-#{ver}_lang.zip"

EXERB = 'exerb'

CLEAN.include('*.exy')
CLEAN.include('**/Thumbs.db')
CLEAN.include('**/_CATALOG.vix')
CLEAN.include('**/*.cache')
CLEAN.include('darkhall.log')
CLEAN.include('out*.txt')
CLEAN.include('save/*.{yml,json}')
CLEAN.include('_patch')

CLOBBER.include('darkhall.exe', 'setting.exe', 'make-mo.exe')
CLOBBER.include('data/*.dat')
CLOBBER.include('data/message/*.dat')
CLOBBER.include('data/dungeon/*.dat')
CLOBBER.include('darkhall-*.zip')
CLOBBER.include('datadoc/*.html')
CLOBBER.include('data/locale/**/*.mo')
CLOBBER.include('setting.ini')
CLOBBER.include('po_base')
CLOBBER.include('po/*.pot')



SRCS = FileList['darkhall_exe.rb']
SRCS.include('lib/**/*.*')

SETTING_SRCS = FileList['setting_exe.rb']
SETTING_SRCS.include('lib/**/*.*')

MAKE_MO_SRCS = FileList['make-mo_exe.rb']




module Util
	def self.zip(dest, srcs)
		if File.exist?(dest) then
			rm dest
		end
	
		list = srcs.to_a.map{|x| %Q|"#{x}"|}.join(' ')
		
		# Rake::FileUtils#sh can't execute very long command on windows.
		# (limit of MS-DOS call?)
		system "zip #{dest} #{list}" or raise 'zip archiving failed.'


		puts "#{dest} created. (#{(File.size(dest) / 1024.0 / 1024.0).to_i}MB)"
	end
	
	def self.get_package_file_list
		re = FileList.new
		re.include('darkhall.exe', 'setting.exe')
		re.include('*.exe.manifest')
		re.include('res/bgm.dat')
		re.include('res/enemy.dat')
		re.include('res/picture.dat')
		re.include('res/dungeon_texture.dat')
		re.include('res/icon/*')
		re.include('res/se/**/*')
		re.include('res/font/KonatuTohaba.ttf')
		re.include('res/font/ume-tgc5.ttf')
		re.include('lib/win32/wxruby2.so')
		re.include('data/*.dat')
		re.include('data/message/*.dat')
		re.include('data/dungeon/?f.dat')
		re.include('data/dungeon/dungeon_form.mpac')
		re.include('data/locale')
		re.include('data/locale/my/translation-guide.txt')
		#re.include('data/locale/**/*.mo')
		re.include('readme.txt')
		
		re.include('manual/*.html')
		re.include('manual/img/ss/*')
		re.include('manual/img/ss_part/*')
		re.include('manual/css/*')

		re.include('doc/**/*')
		#re.include('changelog.txt')
		#re.include('license.txt')
		#re.include('po/**/*.{po,pot}')
		re.include('*.dll')
		re.exclude('msvc*.dll')
		re
	end

	def self.get_linux_package_file_list
		re = get_package_file_list
		re.include('lib/linux/**/*')
		re.include('lib/common/**/*')
		re.include('*_exe.rb')
		re.include('*.sh')
		re.include('bootstrap.rb')
		re.include('linux-readme.txt')
		re.exclude('*.dll')
		re.exclude('darkhall.exe', 'setting.exe')
		re.exclude('*.exe.manifest')
		re.exclude('lib/win32/wxruby2.so')
		re
	end

end



task :default => :build


task :check do
	checkings = [
		[:sh, 'exerb', ['--version']],
		[:sh, 'zip', ['-h']],
		[:sh, 'msginit', ['--help']],
		[:exist, 'res/bgm.dat'],
		[:exist, 'res/dungeon_texture.dat'],
		[:exist, 'res/enemy.dat'],
		[:exist, 'res/picture.dat'],
		[:exist, 'res/se'],
		[:exist, 'res/font'],
		[:exist, 'msvcr71.dll'],
		[:exist, 'msvcp71.dll'],
	]

	msgs = []
	checkings.each do |type, *args|
		case type
		when :exist
			path = args[0]
			if File.exist?(path) then
				msgs << "#{path} - ok"
			else
				msgs << "#{path} - NG (not exists)"
			end
		when :sh
			cmd, cmd_args = args[0], (args[1] || [])
			if sh(cmd, *cmd_args) then
				msgs << "#{cmd} - ok"
			else
				msgs << "#{cmd} - NG (not be installed, or aborts)"
			end
		end
	end

	puts '-' * 60
	puts msgs
end

desc "Package all release files, with Info-zip. (default)"
task :package => [PACKAGE_NAME, LINUX_PACKAGE_NAME, SRC_PACKAGE_NAME, RES_PACKAGE_NAME, LANG_PACKAGE_NAME, :patch]


namespace :package do
	task :win32 => PACKAGE_NAME

	file PACKAGE_NAME => :build do |task|
		packaged = Util.get_package_file_list
		Util.zip(task.name, packaged)
	end

	task :linux => LINUX_PACKAGE_NAME
	
	file LINUX_PACKAGE_NAME => [:mo, :data] do |task|
		packaged = Util.get_linux_package_file_list
		Util.zip(task.name, packaged)
	end
	
	task :src => SRC_PACKAGE_NAME
	
	file SRC_PACKAGE_NAME do |task|
		packaged = FileList.new
		packaged.include('Rakefile.rb')
		packaged.include('*_exe.rb')
		packaged.include('*.exe.manifest')
		packaged.include('lib/**/*')
		packaged.include('data/**/*.rb')
		packaged.include('data/dungeon/dungeon_form.mpac')
		packaged.include('data/locale/my/translation-guide.txt')
		packaged.include('readme.txt')
		packaged.include('src-readme.txt')
		packaged.include('linux-readme.txt')
		packaged.include('doc/**/*')
		packaged.include('res/')
		
		Util.zip(task.name, packaged)
		
	end
	
	task :res => RES_PACKAGE_NAME
	
	file RES_PACKAGE_NAME do |task|
		packaged = FileList.new
		packaged.include('res/**/*')
		packaged.include('*.dll')
		packaged.include('doc/**/*')
		
		packaged.include('manual/*.html')
		packaged.include('manual/img/ss/*')
		packaged.include('manual/img/ss_part/*')
		packaged.include('manual/css/*')

		Util.zip(task.name, packaged)
	end
	
	task :lang => LANG_PACKAGE_NAME
	
	file LANG_PACKAGE_NAME => [:pobase, 'make-mo.exe'] do |task|
		packaged = FileList.new
		packaged.include('make-mo.exe')
		packaged.include('po/my/')
		packaged.include('po/*.pot')
		packaged.include('po_base/*/*.po')
		
		Util.zip(task.name, packaged)
	end


end

=begin
rule '.zip' => '.filelist' do |task|
	rm(task.name, :verbose => true) if File.exist?(task.name)
	sh "#{ZIP} a -tzip #{task.name} @#{task.source}"
end

file 'darkhall_snapshot00.filelist' => packaged + [:build] do |task|
	open(task.name, 'w'){|f|
		f.puts(packaged.to_a)
	}
	
	puts "#{task.name} is maked."
end
=end

desc "Clobber and package."
task :repackage => [:clobber, :package]


desc "Generate exe and lang-files. (default task)"
task :build => [:data, :mo, 'darkhall.exe', 'setting.exe', 'make-mo.exe']

rule '.exe' => '.exy' do |task|
	sh "#{EXERB} -o #{task.name} #{task.sources.first}"
end

data = [
	['darkhall.exy', SRCS, 'darkhall_exe.rb --test-run'],
	['setting.exy', SETTING_SRCS, 'setting_exe.rb'],
	['make-mo.exy', MAKE_MO_SRCS, 'make-mo_exe.rb'],
]
data.each do |target, src_list, cmd|
	file target => src_list do |task|
		sh "ruby -r exerb/mkexy #{cmd}"
		
		mkexy_output = "#{File.basename(task.name, '.exy')}_exe.exy"
		mv(mkexy_output, task.name)
		
		exy = YAML.load_file(task.name)
		exy['general']['kcode'] = 'utf8'
		
		if target == 'make-mo.exy' then
			exy['general']['core'] = 'cui'
		else
			exy['general']['core'] = 'gui'
			exy['file']['msvcr71.dll'] = {'type' => 'dynamic-library'}
			exy['file']['msvcp71.dll'] = {'type' => 'dynamic-library'}
		end
		exy['file'].delete('wxruby2.so')
		#exy['file'].delete_if{|k, v| k =~ /\.\/lib/}
		exy['resource'] ||= {}
		exy['resource']['icon'] = []

		case target
		when 'darkhall.exy'
			[4, 8].each do |c|
				[48, 32, 16].each do |size|
					exy['resource']['icon'] << {'width' => size, 'height' => size, 'color' => c, 'file' => 'res/icon/vit-ruby.ico'}
				end
			end
		when 'setting.exy'
			exy['resource']['icon'] << {'width' => 16, 'height' => 16, 'color' => 8, 'file' => 'res/icon/application-form.ico'}
		end
			
		open(task.name, 'w'){|f| f.write(exy.to_yaml)}
		
	end
end








targets = []
FileList['data/**/[^_]*.rb'].to_a.each do |src|
	dest = src.gsub(/\.rb\z/, '.dat')
	
	file dest => src do |task|
		open(task.name, 'w'){|f|
			f.write([File.read(src)].pack('m'))
		}
		
		puts "#{src} -> #{task.name}"
	end
	targets << dest
end

desc "encrypt data files."
task :data => targets








desc "Make data documents."
task :datadoc => [:mo, :data] do
	require 'tenjin'
	require 'darkhall'
	include DarkHall
	
	Game.init_global_variables_and_data
	
	
	dir_path = './datadoc/'
	tmpl_dir_path = File.join(dir_path, 'template/')
	tenjin = Tenjin::Engine.new(:path => tmpl_dir_path, :layout => 'layout.rbhtml')
	context = Tenjin::Context.new
	
	context[:common_ids] = {}
	COMMON_LINEUP.each_pair do |type, ids|
		next if type == PD_DEBUG
		ids.each do |id|
			context[:common_ids][id] = true
		end
	end
	
	def context.shop_stock_caption(item_id)
		if @common_ids[item_id] then
			'○'
		elsif (stock = GS.shop_stocks[item_id]) then
			stock.to_s
		else
			''
		end
	end
	
	context[:member_classes] = [Fighter, HeavyFighter, Archer, Explorer, Prayer, Magician, Academian, Grappler]
	context[:level_list] = [1, 2, 3, 4, 5, 10, 13, 30, 40, 50]
	
	context[:member_models] = {}
	context[:member_classes].each do |cls|
		context[:member_models][cls] = []
		context[:level_list].each do |level|
			context[:member_models][cls] << cls.new(level, AGE::YOUNG, false)
		end
	end
	
	context[:enemies] = DB.enemies.map{|x| Enemy.new(x.id)}
	
	file_names = %w(
		ability_table exp_table defense_table 3d33_table
		weapon_data armor_data shield_data accessory_data item_data
		treasure_data enemy_data spell_data equipment_table enemy_resist_data
		weapon_attack trick_attack damage_chart hitting_chart damaged_chart
		fee_table
	)
	file_names.each do |name|
		path = File.join(dir_path, "#{name}.html")
		open(path, 'w'){|f|
			f.write tenjin.render("#{name}.rbhtml", context)
		}
		puts "#{path} maked."
	end

end



desc "== clobber"
task :distclean => :clobber

desc "Distclean and build."
task :rebuild => [:clobber, :default]





# Ruby-GetText Task
data = {
	'system' => Dir.glob("lib/*/darkhall/**/*.rb"),
	'dungeon' => Dir.glob("data/dungeon/*f.rb"),
	'spell' => Dir.glob("data/{spell,trick}.rb"),
	'item' => Dir.glob("data/{item,weapon,armor,accessory}.rb"),
	'enemy' => Dir.glob("data/enemy.rb"),
	'message' => Dir.glob("data/message/*.rb") + Dir.glob("data/special_action.rb"),
	'setting' => Dir.glob("setting_exe.rb"),
}

namespace :po do
	data.each_pair do |name, filelist|
		desc "Update pot/po files relating to #{name}."
		task name => filelist do
			require 'gettext/tools'
			ver_id = 'DarkHall beta'
			
			GetText.update_pofiles("darkhall_#{name}", filelist, ver_id)
			
			pot_path = "po/darkhall_#{name}.pot"
			body = File.read(pot_path)
			
			body.sub!(/^\#.+?(?=^[^#])/m){
				<<TEXT
# DarkHall #{name} message catalog for GetText
#
# Created by Team D.H. <team.darkhall@gmail.com>
# This file is distributed under NYSL. <http://www.kmonos.net/nysl/>
#
#, fuzzy
TEXT
			}
			
			File.write(pot_path, body)
		end
	end
end

desc "Update all pot/po files."
task :po => data.keys.map{|x| "po:#{x}"}



desc "Create mo-files"
task :mo do
  require 'gettext/tools'
  GetText.create_mofiles(:mo_root => "./data/locale", :mo_path_rule => "%{lang}", :verbose => true)
end


desc "Create po base (example)"
task :pobase => :po do
	Dir.glob('po/*.pot').each do |pot_path|
		po_name = File.basename(pot_path, '.pot') + '.po'
		
		locales = (ENV['DH_POLANG'] || 'ja,en').split(',')
		
		locales.each do |locale|
			dest = "po_base/#{locale}/#{po_name}"
			mkpath File.dirname(dest)
			
			system "msginit --locale=#{locale} --input=#{pot_path} --output=#{dest} --no-translator"
			po = File.read(dest)
			open(dest, 'wb'){|f|
				f.write po.sub(/Project-Id-Version\: PACKAGE VERSION/, 'Project-Id-Version: DarkHall beta')
			}
		end

	end
end









task :yaml => FileList['save/*.dat'] do |task|
	task.prerequisites.each do |src|
		dest = "#{src}.yml"
		open(src, 'rb'){|f|
			data = MessagePack.unpack(f.read)
			open(dest, 'w'){|f|
				f.write data.to_yaml
			}
		}

		puts "#{src} => #{dest}"
	end
end



task :patch => [PATCH_PACKAGE_NAME]

file PATCH_PACKAGE_NAME => :build do |task|
	table = YAML.load_file('patch_base.yml')
	list = Util.get_package_file_list
	
	list.to_a.each do |src_path|
		next if File.directory?(src_path)
		dest_path = File.join('_patch/', src_path)
	
		if File.exist?(src_path) then
			current = nil
			open(src_path, 'rb'){|f|
				current = Digest::MD5.hexdigest(f.read)
			}
			
			unless current == table[src_path] then
				mkpath(File.dirname(dest_path))
				cp(src_path, dest_path)
			end
		end
	end
	
	cd('_patch') do
		Util.zip("../#{PATCH_PACKAGE_NAME}", FileList['**/*'])
	end
end


task :patchbase => 'patch_base.yml'

file 'patch_base.yml' => :build do |task|
	list = Util.get_package_file_list
	table = {}
	
	$stdout.print 'md5 calculating '
	list.to_a.each do |path|
		if File.file?(path) then
			$stdout.print '.'
			open(path, 'rb'){|input|
				table[path] = Digest::MD5.hexdigest(input.read)
			}
		end
	end
	
	open(task.name, 'w'){|f| f.write table.to_yaml}
	$stdout.print 'ok.'
end


task :testplay => [:data] do
	sh "ruby darkhall_exe.rb -d"
end






# Proc for initializing each spec-tasks by common parameters
setting = proc do |st|
	st.ruby_opts = %w(-Ku)
end

spec_file_pattern = 'spec/incomplete/*.rb'


desc "Verify all spec files."
Spec::Rake::SpecTask.new do |st|
	setting.call(st)
	st.spec_files = FileList[spec_file_pattern]
end

desc "Verify all spec files with specdocs."
Spec::Rake::SpecTask.new(:specd) do |st|
	setting.call(st)
	st.spec_opts << '-fs'
	st.spec_files = FileList[spec_file_pattern]
end



namespace :spec do
	Dir.glob(spec_file_pattern) do |path|
		desc "Verify '#{path}'"
		Spec::Rake::SpecTask.new(File.basename(path, '.rb')) do |st|
			setting.call(st)
			st.spec_files = FileList[path]
		end
	end
end

namespace :specd do
	Dir.glob(spec_file_pattern) do |path|
		desc "Verify '#{path}' with specdocs."
		Spec::Rake::SpecTask.new(File.basename(path, '.rb')) do |st|
			setting.call(st)
			st.spec_opts << '-fs'
			st.spec_files = FileList[path]
		end
	end
end


