import "md5"                         # md5 is needed for automatic checksum-check for changes in files
import "autoclean"                    # autoclean includes the a simple facility for a clean-make-target
import "package/tgz"                  # support for packaging (tar.gz, zip)
import "package/zip"                  # support for packaging (tar.gz, zip)
import "rubydoc"
import "c/dependencies"

require 'build/base_tools.rb'

puts "ERROR: Please run ./configure before building!" unless File.exists?("config.rb")
require 'config.rb'                   # include build-options
    


# get library-dependencies for libSDL
sdlLibs=$config['LIBS'].split(" ")

allSDLlibs=sdlLibs+["-lSDL_image","-lSDL_ttf","-lpng"]
glLibs=$config["LIBGL"].split(" ")

# configure source-directories.
# DLLs will be build for each directory and in the given order.
# on the left the directory containing the sources is given
# on the right the dependencies, which can be one of the following:
# - an external library, which then marked by "-l" in front, like "-lz" for the z-library
# - an internal dependency on a directory
# NOTE: dependencies are not automatically inherited, you have to include them yourself!

rubyLib=[$config['RUBYLIB']]

sourceDeps=[
	["ext/external",["-lz"]+sdlLibs],
	["ext/basic",["ext/external","-lz"]+sdlLibs+rubyLib],
	["ext/math",["ext/external","ext/basic"]],
	["ext/video",["ext/external","ext/basic","ext/math"]+glLibs+allSDLlibs],
	["ext/gui",["ext/basic","ext/math","ext/video"]+allSDLlibs],
	["ext/sound",["ext/basic","-lSDL_mixer"]+sdlLibs],
	["ext/3dengine",["ext/external","ext/basic","ext/math","ext/video","ext/gui"]+glLibs+sdlLibs],
	["ext/game",["ext/basic","ext/math","ext/video","ext/gui","ext/3dengine"]+glLibs+sdlLibs],
]

$sourceDeps=sourceDeps

sourceDirs=sourceDeps.collect{|a|a[0]}    # collect dirs containing source (in the correct order !)

externalIncludes=$config['CFLAGS']
#externalIncludes+=`sdl-config --cflags`.gsub("\n","")

# sitearchdir - include in usr/local
rubyIncDir=getConfig("archdir")
    
# gather include-directories (separately from other cflags, so they can be used for swig later on
var :INCLUDES => sourceDirs+[rubyIncDir,"."]

var :INCLUDESTR => var[:INCLUDES].collect{|d|"-I#{d}"}.join(" ")+" "+externalIncludes    # build include-string (-I...)


# configure cflags out of config.rb
cflags=""
cflags+=" -DGCDEBUG" if $config["gcdebug"]   # enable debuggin of garbage-collection
cflags+=" -g -O0"    if $config["debug"]     # disable optimizations for better debugging
cflags+=" -DNDEBUG -DMNDEBUG"  if not $config["debug"] # disable debug-output
cflags+=" -O0 -g"       unless $config["debug"] # enable optimizations
#cflags+=" -O2"       unless $config["debug"] # enable optimizations
cflags+=" -DMPROFILE" if $config["profile"]  # enable profiling
	

var :CFLAGS => var[:INCLUDESTR]+cflags          # store cflags in "var" for later read-out while compiling

var.env %w(CC CFLAGS)                           # get cflags from environment

###########################################
# all-target
buildLibs=sourceDirs.collect{|d|"ext/"+"lib"+makeLibName(d)+".so"}
interfaceLibs=sourceDirs[1..-1].collect{|d|"ext/"+makeLibName(d)+".so"} # exclude "ext/external"
allTargets = buildLibs + interfaceLibs
task :all => allTargets
#
###########################################



   

###########################################
# build libraries (without swig)
#
sourceDeps.each{|pair|
	dir,dep=pair                                                               # get directory and dependencies
	target="ext/"+"lib"+makeLibName(dir)+".so"                    # make library name like "ext/libantargisgui.so"
	tsources=Dir[dir+"/*.cc"].select{|f|not f=~/swig/}            # get all *.cc files (without the swig-generated file)
	tsources.collect!{|f|f.sub_ext("oo")}                                      # translate the .cc files to .oo
	tsources+=Dir[dir+"/*.c"].collect!{|f|f.sub_ext("o")}         # add *.c files if there are any
	extlibs=[]
    
    #puts "TARGET:",target
    #puts "TSOURCES:",tsources
    
	dep.each{|d|
		if d[0..0]=="-"
			extlibs << d                                                           # gather external libraries (-lz)
		else
			extlibs+=["ext/lib"+makeLibName(d)+".so"]             # gather internal deps like (ext/libantargisbasic.so)
		end
	}
	task target => tsources do |t|
		# build command
		sources=t.prerequisites
        
		if ENV['WINDIR']
                extlibs=extlibs.collect{|s|s.gsub(/.*lib(.*)\.so/,'-l\1')}
                
                
				#puts "SOURCES #{sources}"
				#puts "EXTLIBS #{extlibs}"
				sources=sources.select{|f|not f=~/\.so/}
		end
		cmd=makeCommand("LINK_SHARED",sys.expand_path(U2W(t.name)), (sources.collect{|f|sys.expand_path(f)}+extlibs).join(" "))
        #puts "------",cmd,"--------------!"
		sys cmd
		puts
		if isWindows
				sys "copy #{sys.expand_path(t.name).gsub("/",Dir.separator)}.a #{sys.expand_path(t.name).sub(/\.so/,".dll").gsub("/",Dir.separator)}.a"
				puts
		end
	end
}
#
###########################################


###########################################
# build extension libraries
#
sourceDeps.each{|pair|
	dir,dep=pair
	libname=makeLibName(dir)
	target="ext/"+makeLibName(dir)+".so"

	# FIXME:re-include this
	tsources=[]
	tsources+=[dir+"/"+libname+"swig.cc"]
	tsources.collect!{|f|f.sub_ext("oo")}
	#tsources+=["ext/lib"+makeLibName(dir)+".so"]
	extlibs=[] #["-l"+makeLibName(dir)]
    
    if isWindows
	    extlibs+=["-l"+makeLibName(dir)]
    end
    
	dep.each{|d|
		if d[0..0]!="-" and d!="ext/external"
			if isWindows
				extlibs+=["-l"+makeLibName(d)]
			else
				# take some direct path instead ???
				#tsources+=["ext/lib"+makeLibName(dir)+".so"]
				extlibs+=["ext/lib"+makeLibName(dir)+".so"]
			end
		end
	}
    
    puts "EXTLIBS:#{extlibs}"
    #tsources+=rubyLib
    
    #puts "TARGET:",target
    #puts "SOURES:",tsources
    #puts "---"
	task target => tsources do |t|
		cmd=makeCommand("LINK_SHARED",sys.expand_path(t.name), (t.prerequisites.collect{|f|sys.expand_path(f)}+extlibs+rubyLib).join(" "))
        #puts "------",cmd,"--------------!"
		sys cmd
		puts
	end
}
###########################################


depC=lambda{|target|
	source=target.gsub(/\.o$/,".c").gsub(/\.oo$/,".cc")
	target=sys.expand_path(target)
	deps=getDependencies(target)
	#puts "MUH:"+([source]+deps).join(":::")
	[source]+deps
}    

###########################################
# build c
#
gen Rule, '.o' => depC do |t|
	cmd=makeCommand("CC_CALL",sys.expand_path(t.name),"#{var :CFLAGS} #{(t.source)}")
	sys cmd
	puts
end
###########################################

###########################################
# build c++
#
gen Rule, '.oo' => depC do |t|
	cmd=makeCommand("CXX_CALL",sys.expand_path(t.name),"#{var :CFLAGS} #{(t.source)}")
	sys cmd
	puts
end
#
###########################################


###########################################
# swig - interfacing for ruby
#
swigSrc = lambda { |target| 
	dir=getDirUnix(target)
    #puts "TARGET:#{target} DIR:#{dir}"
	name=makeLibName(dir)
	a=[target.sub(/#{name}swig.*/,"interface.i")]+sys["build/*.i"]+importsForInterface(target).split(":") 
    puts "A: #{a}"
    puts "name: #{name}"
    puts "dir: #{dir}"
    puts "target: #{target}"
    a
}

gen Rule, /^.*swig.(cc|h)$/ => swigSrc do |t|

	puts "SOURCE #{t.source} #{t.name}"

	cmd=makeCommand("SWIG_CALL",sys.expand_path(t.name.gsub(/\.h$/,".cc")),"-DAGEXPORT -Ibuild -I#{sys.expand_path(getDir(t.name))} #{var :INCLUDESTR} #{sys.expand_path(t.source)}".gsub("/",Dir.separator))
	sys cmd
	puts

	incs="-DAGEXPORT -Ibuild -I#{sys.expand_path(getDir(t.name))} #{var :INCLUDESTR}"
	out=".deps"+Dir.separator+sys.expand_path(t.name).gsub("/","_")
	cmd=makeCommand("SWIGDEPS",out,incs+" "+sys.expand_path(t.name.gsub(/[0-9_a-z]*\.(h|cc)$/,"interface.i")))
	sys cmd
	puts

end
#
###########################################



###########################################
# interface-files for swig
#

def importsForInterface(name)
#puts "?=="
	$sourceDeps.each{|t|
		if name=~/#{t[0]}/
			return t[1].select{|f|not f=~/-.*/}.select{|f|not f=~/external/}.collect{|f|f+"/interface.i"}.join(":")
		end
	}
	return ""
end

interfaceSrc = lambda { |target| 
	list=Dir[getDirUnix(target)+"/"+"*.h"].select{|f|not f=~/swig.h/}+Dir["build/*.rb"] # FIXME:replace
	list+=importsForInterface(target).split(":")
	list
}

gen Rule, /^.*interface.i$/ => interfaceSrc do |t|
    cmd=makeCommand("CREATEINTERFACE",getDirUnix(sys.expand_path(t.name)),importsForInterface(t.name))
	sys cmd
end
#
###########################################

###########################################
# make swig-sources
#
task :swigSources =>sourceDirs.select{|d|not d=~/external/}.collect{|d|d+"/"+makeLibName(d)+"swig.cc"} do
end
#
###########################################

###########################################
# make rant-stand-alone
#
task :rantStandAlone =>[] do |t|
	cmd="rant-import --force --auto build.rb"
    sys cmd
end
#
###########################################

###########################################
# build extensions
#
task :extensions=>allTargets do |t|
end
#
###########################################


###########################################
# build source-distribution
#
files=(sys["build/**/*"]+sys["ext/**/*"]+sys["ruby/**/*.rb"]+sys["data/**/*"]+sys["*"]).select{|f|not (f=~/~/ or f=~/.xcf/ or f=~/swig/ or f=~/packages/ or f=~/\.o/ or f=~/\.so/)}
#puts files
#exit

if isWindows
    sourcePkg=gen Package::Zip, "packages","antargis-source-"+extendCommand($config,"version"), :files => files
else
    sourcePkg=gen Package::Tgz, "packages","antargis-source-"+extendCommand($config,"version"), :extension => ".tar.gz", :files => files
end

task :dist=>[:swigSources,:rantStandAlone,sourcePkg.path] do |t|
end
#
###########################################

###########################################
# build source-distribution
#
if isWindows
    binpkg=gen Package::Zip, "packages","antargis-"+extendCommand($config,"system")+"-"+extendCommand($config,"version"), :files => (sys["ext/*.so"]+sys["ruby/**/*.rb"]+sys["data/**/*"]+sys["*"]).select{|f|not (f=~/~/ or f=~/.xcf/)}
else
    binpkg=gen Package::Tgz, "packages","antargis-"+extendCommand($config,"system")+"-"+extendCommand($config,"version"), :extension => ".tar.gz", :files => (sys["ext/*.so"]+sys["ruby/**/*.rb"]+sys["data/**/*"]+sys["*"]).select{|f|not (f=~/~/ or f=~/.xcf/)}
end

task :bindist=>[:extensions,binpkg.path] do |t| #"packages/antargis-"+extendCommand($config,"version")+".tar.gz"] do |t|
end
#
###########################################

# # build documentation
# task :doc do
# 	puts "running doxygen"
# 	`doxygen Doxyfile`
# 	rubies=`find -name "*.rb"`.split("\n").select{|f|not (f=~/(contrib|skat|test)/)}.join(" ")
# 	readmes=`find -name "README"`.split("\n").select{|f|not (f=~/(contrib|skat|test)/)}.join(" ")
# 	headers=`find -name "*.h"`.split("\n").select{|f|not (f=~/(contrib|skat|test)/)}.join(" ")
# 	`rdoc -m README --op docs/ruby #{rubies} #{readmes}` # --exclude "(\\.cc|\\.c|skat|test\/|contrib)"`
# end

desc "Generate html documentation for c++-sources"
task :doxygen=>[] do |t|
			# run doxygen in here
 			`doxygen build/Doxyfile`
 end
desc "Generate html documentation."
	gen RubyDoc do |t|
			a=sys["**/README"]+sys["ruby/**/*.rb"]+sys["INSTALL"]+sys["build/*.rb"]+sys["configure"]+sys["Rantfile"]
			a=a.select{|f|not f=~/_test/}
			t.opts = %w(--title Battles\ of\ Antargis --main README --diagram)+a
			t.dir = "docs/ruby"
	end

###########################################
# configure - clean-task
gen AutoClean, :clean
var[:clean].include "**/marker.i"   # not needed any more - managed by Rule
var[:clean].include "ext/*.so"
var[:clean].include ".deps"
###########################################

task :check_c_prgs do
	require 'build/testing.rb'
	
	Cmd.setQuiet(true)
	
	testFiles=Dir[File.join("ext/**/tests/*.cc")]
	
	testFiles.each{|file|
		Testing.runCTest(file)
	}
	puts Testing.getStats

end

task :check=> [:check_c_prgs] do
end
