# signature { license=0, seed=277031123, key="26d92f5a4793016b0f503cdb512cc1e4" }
require 'paths' 'lms'
local xmlpro = require('xmlpro')





local format = string.format
local insert, concat = table.insert, table.concat

local XmlProUserID, XmlProPassword
local config =
	{
		default = 'default.cfg' ;
		backup  = 'backup.cfg' ;
		file    = 'lms.cfg' ;
		update  = 'update.cfg' ;
	}

local f = io.open( 'install.log' )
local chksum = f:read('*a')
f:close()

function config.secret( cfg, var )
	local md5, v = require('md5'), cfg[var..'Password']
	if v then
		if v == '' then return v end
		return md5.hex( md5.exor( chksum, md5.exor( v, var ) ):sub(1,#v) )
	end
	return ''
end

function config.password( cfg, var )
	local md5, v = require('md5'), cfg[var..'Secret']
	if v then
		if v == '' then return v end
		v = v:gsub( '(%x%x)', function(hh) return string.char('0x'..hh) end )
		return md5.exor( chksum, md5.exor( v, var ) ):sub(1,#v)
	else
		return cfg[ var..'Password' ]
	end
end






function config.read( cfgName, cfg )
	cfg = cfg or {}

	local code = loadfile( cfgName, 't', cfg )
	if code then
		code()


	end
	return cfg
end






local function dump( value, as, print )
	local H = {}
	local printf = print or function( fmt, ... ) insert( H, format( fmt, ...))  end
	local out, ndx
	local tab, nl = as.tab or '\t', as.nl or '\n'

	local function printTable( T, level )
		printf( '%s%s{%s', nl, tab:rep(level), nl )
		level = level +1
		local comma, indent = '', tab:rep( level )
		for k,v in next,T do
			if type(v) ~= 'function' then
				printf( '%s%s%s', comma, indent, as.idx) ndx( k ) printf( as.eq ) out( v, level )
				comma = as.comma
			end
		end
		printf( '%s%s}', nl, tab:rep(level-1) )
	end

	local function printArray( T, level )
		printf( '%s%s[ %s', nl, tab:rep(level), nl )
		level = level +1
		local comma, indent = '', tab:rep( level )

		for i = 0, #T do
			local v = T[i] or ''
			printf( '%s%s', comma, indent) out( v, level )
			comma = as.comma
		end
		printf( '%s%s]', nl, indent:rep(level-1))
	end

	out = function( val, level )
		local t = type( val )
		if     t == 'string'  then printf( '%q', val )
		elseif t == 'number'  then printf( '%s', tostring(val) )
		elseif t == 'boolean' then printf( val and 'true' or 'false' )
		elseif t == 'table'   then
			if as.antiloop[ val ] then
				printf( '%s', tostring( val ))
			else
				as.antiloop[ val ] = true
				if val.isArray or as.array and val[1] then
					printArray( val, level )
				else
					printTable( val, level )
				end
				as.antiloop[ val ] = nil
			end
		else printf( as.null )
		end
	end

	ndx = as.ndx or out
	as.antiloop = as.antiloop or {}
	out( value,0 )
	if not print then return concat( H ) end
end

function config.JSON( cfg, printf )
	return dump( cfg, { null = 'null', idx='', eq = ':', comma = ',\n' }, printf )
end

function config.json( cfg, printf )
	return dump( cfg, { null = 'null', idx='', eq = ':', tab='', nl='', comma = ',', array = '[]'  }, printf )
end

function config.Lua( cfg )
	local H = {}
	local antiloop={}
	for k,v in next, cfg do
		if type(v) ~= 'function' then
			insert( H, format( '%s = %s', k, dump( v, { null = 'nil',  idx='[', eq = ']=', comma = ';\n', antiloop=antiloop } )))
			if type(v) == 'table' then antiloop[v]=true end
		end
	end
	return concat( H, ';\n')
end



local function postcheck( cfg )

	for _, var in pairs{ 'XmlPro', 'Smtp', 'Client' } do
		if cfg[ var..'Password' ] ~= '********' then

			cfg[ var..'Secret' ] =  config.secret( cfg, var )
			cfg[ var..'Password' ] = '********'
		end
	end

	XmlProUserID = cfg.XmlProUserID
	XmlProPassword = config.secret( cfg, 'XmlPro' )

	setmetatable( cfg, {__index = config })

	return cfg
end





function config.write( cfg )
	if not cfg then return end
	cfg = postcheck( cfg)
	cfg.version = '1.0.3'

	os.remove( config.backup )
	os.rename( config.file, config.backup )
	local cfgFile = io.open( config.file, 'w' )
	if not cfgFile then return end
	cfgFile:write( config.Lua( cfg ))
	cfgFile:close()
	os.remove( config.update )
end




function config.change( cfg, changes )
	cfg = cfg or {}

	local code,error = load( changes, nil, 't', cfg )
	if code then
		code()
	else
		print ("config:change->error:", error)
		return nil, error
	end
	cfg.i18n = nil;

	return cfg
end



function config.load( )
	local cfg = {i18n=i18n or function(t) return t end}
	cfg = config.read( config.default, cfg)
	cfg = config.read( config.backup, cfg)
	cfg = config.read( config.file, cfg)
	cfg = config.read( config.update, cfg )
	cfg = postcheck( cfg)

	return cfg
end

function config.XmlPRO( request, ... )

	xmlpro.login( XmlProUserID or '', XmlProPassword or '' )
	local ok, content = pcall( xmlpro.post, format( request, ... ) )

	return ok and content or ''
end

setmetatable( config, {__call = config.load })

return config
