local u = dofile('common.lua')
local default = function(var,def)
	local v = os.getenv(var)
	if v then return v else return def end
end
local function coalesce(x,...)
	if x ~= nil then return x else
		if select('#',...) == 0 then return nil end
		return coalesce(...)
	end
end
local posixes = {
	linux = true; osx = true;
	android = true; haiku = true;
}
local default_os = 'linux'
local defaultlist = function(env, ...)
	local e = os.getenv(env)
	local lst = {}
	if e then
		for v in e:gmatch('([^:]*)') do lst[#lst + 1] = v end
		return lst
	else return {...} end
end
local conf = {
	pkg = {};
	dist      = default('parsav_dist', coalesce(
		os.getenv('NIX_PATH')  and 'nixos',
		os.getenv('NIX_STORE') and 'nixos',
	''));
	tgttrip   = default('parsav_arch_triple'); -- target triple, used in xcomp
	tgtcpu    = default('parsav_arch_cpu'); -- target cpu, used in xcomp
	tgthf     = u.tobool(default('parsav_arch_armhf',true)); 
	doc       = {
		online  = u.tobool(default('parsav_online_documentation',true)); 
		offline = u.tobool(default('parsav_offline_documentation',true)); 
	};
	outform   = default('parsav_emit_type', 'o');
	endian    = default('parsav_arch_endian', 'little');
	prefix    = default('parsav_install_prefix', '.');
	build     = {
		id = u.rndstr(6);
		release = u.ingest('release');
		when = os.date();
	};
	feat = {};
	debug = u.tobool(default('parsav_enable_debug',true)); 
	backends = defaultlist('parsav_backends', 'pgsql');
	braingeniousmode = false;
	embeds = {
		-- TODO with gzip compression, svg is dramatically superior to webp
		-- we should add support for content-encoding headers and pre-compress
		-- the damn things before compiling (also making the binary smaller)
		{'style.css', 'text/css'};
		{'live.js', 'text/javascript'}; -- rrrrrrrr
		{'default-avatar.webp', 'image/webp'}; -- needs inkscape-exclusive svg features
		{'bell.svg', 'image/svg+xml'};
		{'heart.webp', 'image/webp'};
		{'retweet.webp', 'image/webp'};
		{'padlock.svg', 'image/svg+xml'};
		{'warn.svg', 'image/svg+xml'};
		{'query.webp', 'image/webp'};
	};
	default_ui_accent = tonumber(default('parsav_ui_default_accent',323));
}
if os.getenv('parsav_let_me_be_an_idiot') == "i know what i'm doing" then
	conf.braingeniousmode = true -- SOUND GENERAL QUARTERS
end
if u.ping '.fslckout' or u.ping '_FOSSIL_' then
	if u.ping '_FOSSIL_' then default_os = 'windows' end
	conf.build.branch = u.exec { 'fossil', 'branch', 'current' }
	conf.build.checkout = (u.exec { 'fossil', 'sql',
		[[select value from localdb.vvar where name = 'checkout-hash']]
	}):gsub("^'(.*)'$", '%1')
end
conf.os    = default('parsav_host_os', default_os)
conf.tgtos = default('parsav_target_os', default_os)
conf.posix = posixes[conf.os]
conf.exe   = u.tobool(default('parsav_link',not conf.tgttrip)) -- turn off for partial builds
conf.prefix_conf = default('parsav_install_prefix_cfg', conf.prefix)
conf.prefix_bin = default('parsav_install_prefix_cfg', conf.prefix)
conf.prefix_static = default('parsav_install_prefix_static', nil)
conf.build.origin = coalesce(
	os.getenv('parsav_builder'),
	string.format('%s@%s', coalesce (
		os.getenv('USER'),
		u.exec{'whoami'}
	), u.exec{'hostname'}) -- whoami and hostname are present on both windows & unix
)
if conf.build.release then
	local v = conf.build.release
	conf.build.str = string.format('release %s', conf.build.release)
else
	conf.build.str = string.format('build %s-%s', conf.build.id, conf.build.origin)
	if conf.build.branch then
		conf.build.str = conf.build.str .. string.format(':%s(%s)',
			conf.build.branch, string.sub(conf.build.checkout,1,10))
	end
end

if conf.tgtos == 'linux' then
	conf.feat.randomizer = default('parsav_feat_randomizer', 'kern')
else
	conf.feat.randomizer = default('parsav_feat_randomizer', 'libc')
end

local choplib = function(l)
	if string.sub(l,1,3) == 'lib' then return string.sub(l,4) end
	return l
end
local fallback = dofile('pkgdata.lua')
local libfind do local mkf = function(p)
		return function(l) return string.format(p,l) end
	end
	local unx = function(p)
		return function(l)
			if string.sub(l,1,3) == 'lib'
				then return string.format('%s.%s',l,p)
				else return string.format('lib%s.%s',l,p)
			end
		end
	end

	libfind = {
		linux = { static = unx 'a', dynamic = unx 'so'; };
		osx   = { dynamic = mkf '%s.dylib'; };
		win   = { dynamic = mkf '%s.dll'; };
	}
end
local pkg = function(name)
	local fbo = fallback[name] and fallback[name].osvars and coalesce(
		fallback[name].osvars[conf.os .. '_' .. conf.dist],
		fallback[name].osvars[conf.os]
	)
	local fbv = fallback[name] and fallback[name].vars
	local fb = fallback[name]
	local pkgenv = function(e)
		return os.getenv(string.format('parsav_pkg_%s_%s',name,e))
	end
	local nul = function() end
	local pkc, pkv = nul, nul
	local locdep = false
	local cnfvar = function(v,e)
		local eval = function(e)
			if type(e) == 'function'
				then return e(conf)
				else return e
			end
		end
		return coalesce(
			pkgenv(v),
			pkv(e or v),
			(fbo and eval(fbo[v])),
			(fbv and eval(fbv[v])))
	end
	local name = cnfvar('override') or name
	local pcname = coalesce(cnfvar('pcname'), name)
	if conf.posix then
		pkc  = function(...) if locdep then return nil end
			return u.exec { 'pkg-config'; pcname; ...  } end
		local pkcv = function(...) return u.exec({ 'pkg-config'; pcname; ...  }, true) end
		if pkcv('--exists') == 0 then
			pkv = function(v)
				if locdep then return nil end
				return pkc('--variable', v)
			end
		else pkc = nul end
	else
		print '(warn) configuring on non-POSIX OS, all relevant paths must be specified manually in environment variables or build will fail!'
	end
	locdep = u.ping('./lib/' .. name)
	local incdir, libdir, prefix
	if locdep then
		prefix = './lib/' .. name
		libdir = prefix .. coalesce(cnfvar('libbuilddir'),cnfvar('builddir'),'')
		incdir = prefix .. coalesce(cnfvar('srcincdir'),cnfvar('builddir'),'/include')
	else
		prefix = coalesce(cnfvar('prefix'), '/usr')
		libdir = cnfvar('libdir')
		incdir = cnfvar('incdir','includedir')
	end
	libdir = libdir or prefix .. '/lib'
	incdir = incdir or prefix .. '/include'

	local libstr = pkc '--libs-only-l' -- (--static is not reliable)
	local libs = fb and fb.libs or {}
	local linkstatic = locdep
	if (not locdep) and libstr then
		libs = {}
		for m in string.gmatch(libstr, '-l(%g+)') do
			libs[#libs + 1] = m
		end
	else
		if #libs == 0 then libs = { name } end
	end

	conf.pkg[name] = {
		prefix = prefix;
		libdir = libdir;
		incdir = incdir;
		dylibs = {}, statlibs = {};
	}
	local me = conf.pkg[name]
	
	local lf = libfind[conf.os]
	if lf.dynamic then me.dylibs   = u.map(libs, lf.dynamic) end
	if lf.static  then me.statlibs = u.map(libs, lf.static)  end

	if linkstatic then
		local ldf = {}
		for _,v in pairs(me.statlibs) do
			local fl = libdir .. '/' .. v
			if u.ping(fl) then ldf[#ldf+1] = fl end
		end
		me.linkargs = ldf
	else
		local arg = choplib(name)
		local linkline = libstr
		if not linkline and #libs == 0 then
			linkline = string.format('-l%s', arg)
		elseif not linkline then linkline = '' end
		me.linkargs = {
			string.format('-L%s', me.libdir);
		}
		for m in string.gmatch(linkline, '(%g+)') do
			me.linkargs[#me.linkargs+1] = m
		end

		-- siiiiigh
		for _,l in pairs(libs) do
			local sw = string.format('-l%s', choplib(l)) 
			local found = false
			for _,a in pairs(me.linkargs) do
				if a == sw then found = true break end
			end
			if not found then
				me.linkargs[#me.linkargs+1] = sw
			end
		end
	end
end

pkg('mbedtls')
pkg('mongoose')
pkg('json-c')
pkg('libc')
pkg('libpq')

return conf
