require 'rake/loaders/makefile'

#################
# Configuration #
#################

NAME = 'qGo'
APPVERSION = /#define +VERSION +"([^"]+)"/.match(File::read('config.h'))[1]

GNUGO = '/usr/local/bin/gnugo'
QTDIR = '/usr/local/qt335-ppc'

UIC = "#{QTDIR}/bin/uic -nounload"
MOC = "#{QTDIR}/bin/moc"
CXX = 'c++'
CXXFLAGS = "-Os -fno-exceptions -fno-check-new -Wno-deprecated -DQT_THREAD_SUPPORT -DHAVE_CONFIG_H "
INCLUDES = "-I#{QTDIR}/include -I."
LDFLAGS = "-L#{QTDIR}/lib -bind_at_load"
LIBS = "-lqt-mt -lz -framework Carbon -framework Quicktime"
MAKEDEPEND = '/usr/X11R6/bin/makedepend'

#####################
# Support functions #
#####################

def installRule(dir, file)
	target = File::join(dir, File::basename(file))
	file(target => [dir, file]) do |t|
		cp(file, target)
	end
end

def installTask(taskName, dir, files)
	if files.is_a?(String)
		files = [files]
	end

	array = []
	for f in files do
		array << File::join(dir, File::basename(f))
		installRule(dir, f)
	end
	task(taskName => array)
end

def bundleDir(dir)
	file(dir) do |t|
		sh("/Developer/Tools/SetFile -a B #{dir}")
	end
end

####################
# Bundle structure #
####################
directory(BUNDLEDIR = "#{NAME}.app")
directory(CONTENTSDIR = "#{BUNDLEDIR}/Contents")
directory(BINDIR = "#{CONTENTSDIR}/MacOS")
directory(RESOURCEDIR = "#{CONTENTSDIR}/Resources")

bundleDir(BUNDLEDIR)

installTask(:setup, CONTENTSDIR, 'mac/Info.plist')
task(:bundle => :setup)

##############
# App binary #
##############

sources = %w(
	board.cpp
	boardhandler.cpp
	gamedialog.cpp
	gamestable.cpp
	gametree.cpp
	group.cpp
	helpviewer.cpp
	igsconnection.cpp
	imagehandler.cpp
	interfacehandler.cpp
	main.cpp
	maintable.cpp
	mainwidget.cpp
	mainwin.cpp
	mainwindow.cpp
	mark.cpp
	matrix.cpp
	misc.cpp
	move.cpp
	msg_handler.cpp
	noderesults.cpp
	parser.cpp
	playertable.cpp
	preferences.cpp
	qgo.cpp
	qgo_interface.cpp
	qgtp.cpp
	qnewgamedlg.cpp
	searchpath.cpp
	setting.cpp
	sgfparser.cpp
	stone.cpp
	stonehandler.cpp
	tables.cpp
	telnet.cpp
	textview.cpp
	tip.cpp
	tree.cpp
	xmlparser.cpp
)

uis = %w(
	clientwindow_gui.ui
	gameinfo_gui.ui
	gui_dialog.ui
	mainwidget_gui.ui
	newgame_gui.ui
	newlocalgame_gui.ui
	noderesults_gui.ui
	normaltools_gui.ui
	nthmove_gui.ui
	preferences_gui.ui
	qnewgamedlg_gui.ui
	scoretools_gui.ui
	talk_gui.ui
	textedit_gui.ui
	textview_gui.ui
)

mocs = %w(
	board.h
	gamedialog.h
	gamestable.h
	gametree.h
	helpviewer.h
	igsconnection.h
	maintable.h
	mainwidget.h
	mainwin.h
	mainwindow.h
	noderesults.h
	parser.h
	playertable.h
	preferences.h
	qgo.h
	qgo_interface.h
	qgtp.h
	qnewgamedlg.h
	searchpath.h
	tables.h
	telnet.h
	textview.h
	tip.h
)

cleanfiles = []

for ui in uis
	source = "#{File::basename(ui, '.ui')}.cpp"
	header = "#{File::basename(ui, '.ui')}.h"
	file(header => ui) do |task|
		sh("#{UIC} -o #{task.name} #{task.prerequisites[0]}")
	end
	file(source => [header, ui]) do |task|
		sh("#{UIC} -i #{task.prerequisites[0]} -o #{task.name} #{task.prerequisites[1]}")
	end
	sources.push(source)
	mocs.push(header)
	cleanfiles.push(source)
	cleanfiles.push(header)
end

for header in mocs
	moc = "#{File::basename(header, '.h')}.moc.cpp"
	file(moc => header) do |task|
		sh("#{MOC} -o #{task.name} #{task.prerequisites[0]}")
	end
	sources.push(moc)
	cleanfiles.push(moc)
end

objects = []
for source in sources
	object = "#{File::basename(source, '.*')}.o"
	file(object => source) do |task|
		sh("#{CXX} #{CXXFLAGS} #{INCLUDES} -o #{task.name} -c #{task.prerequisites[0]}")
	end
	objects.push(object)
	cleanfiles.push(object)

	depfile = "#{File::dirname(source)}/.#{File::basename(source, '.*')}.dep.mf"
	file(depfile => source) do |task|
		sh("#{MAKEDEPEND} -f- -- #{INCLUDES} -- #{task.prerequisites} > #{task.name} 2> /dev/null")
	end
	import depfile
	cleanfiles.push(depfile)
end

file("#{BINDIR}/#{NAME}" => [BINDIR, *objects]) do |task|
	sh("#{CXX} #{LDFLAGS} -o #{task.name} #{task.prerequisites[1..-1].join(' ')} #{LIBS}")
end

file("#{BINDIR}/gnugo" => GNUGO) do |task|
	cp(GNUGO, task.name)
end

task(:binary => "#{BINDIR}/#{NAME}")
task(:binary => "#{BINDIR}/gnugo")
task(:bundle => :binary)

############
# App data #
############

directory(BACKGROUNDSDIR = "#{RESOURCEDIR}/Backgrounds")

installTask(:data, BACKGROUNDSDIR, %w(
	pics/barcelona_cherry.jpg
	pics/birch.jpg
	pics/eurobeech.jpg
	pics/goldenbeech.jpg
	pics/kaya.png
	pics/lemontree.jpg
	pics/manitoba.jpg
	pics/maple.jpg
	pics/plain.png
	pics/synthetic_1.png
	pics/synthetic_2.png))
installTask(:data, RESOURCEDIR, Dir::glob("translations/*.qm"))
installTask(:data, RESOURCEDIR, Dir::glob("sounds/*.wav"))
installTask(:data, RESOURCEDIR, 'mac/qgo.icns')

task(:bundle => :data)

#######################
# Disk Image Creation #
#######################

task(:image => :bundle) do |t|
	imageName = "#{NAME}-#{APPVERSION}"
	imagePath = "/Volumes/#{imageName}"

	if File::directory?(imagePath)
		sh("diskutil eject #{imagePath}")
	end

	sh("hdiutil create -fs HFS+ -volname #{imageName} -ov -type SPARSE -attach #{imageName}")
	sh("strip #{BINDIR}/qGo")
	cp_r([BUNDLEDIR, '../COPYING', '../ChangeLog'], imagePath)
	cp('mac/Image-DS_Store', "#{imagePath}/.DS_Store")
	sh("diskutil eject #{imagePath}")

	rm_f("#{imageName}.dmg")
	sh("hdiutil convert #{imageName}.sparseimage -format UDZO -o #{imageName}")
	rm("#{imageName}.sparseimage")
end

################
# Main targets #
################

task(:default => :bundle)

task(:clean) do |task|
	rm_rf(cleanfiles)
	rm_rf(BUNDLEDIR)
end
