#!/usr/bin/ruby

print "This script attempts to show how to run an add/remove/replace brick transform.\n"

testcase = {}

# add your logical orderings as a 'test'.

# replica = 2, simple setup
testcase['test1a'] = []
testcase['test1a'].push( {'host' => 'annex1.example.com', 'path' => '/data/brick1'} )
testcase['test1a'].push( {'host' => 'annex2.example.com', 'path' => '/data/brick1'} )

testcase['test1a'].push( {'host' => 'annex3.example.com', 'path' => '/data/brick2'} )
testcase['test1a'].push( {'host' => 'annex4.example.com', 'path' => '/data/brick2'} )

testcase['test1a'].push( {'host' => 'annex1.example.com', 'path' => '/data/brick3'} )
testcase['test1a'].push( {'host' => 'annex2.example.com', 'path' => '/data/brick3'} )

testcase['test1a'].push( {'host' => 'annex3.example.com', 'path' => '/data/brick4'} )
testcase['test1a'].push( {'host' => 'annex4.example.com', 'path' => '/data/brick4'} )

# and then add:

### versus ###

# this fails because the logical order is different...! this should always fail...
testcase['test1b'] = []
testcase['test1b'].push( {'host' => 'annex1.example.com', 'path' => '/data/brick1'} )
testcase['test1b'].push( {'host' => 'annex2.example.com', 'path' => '/data/brick1'} )

testcase['test1b'].push( {'host' => 'annex3.example.com', 'path' => '/data/brick2'} )
testcase['test1b'].push( {'host' => 'annex4.example.com', 'path' => '/data/brick2'} )

testcase['test1b'].push( {'host' => 'annex1.example.com', 'path' => '/data/brick3'} )
testcase['test1b'].push( {'host' => 'annex2.example.com', 'path' => '/data/brick3'} )

testcase['test1b'].push( {'host' => 'annex3.example.com', 'path' => '/data/brick4'} )
testcase['test1b'].push( {'host' => 'annex4.example.com', 'path' => '/data/brick4'} )

# and then add:

testcase['test1b'].push( {'host' => 'annex5.example.com', 'path' => '/data/brick5'} )
testcase['test1b'].push( {'host' => 'annex6.example.com', 'path' => '/data/brick5'} )

testcase['test1b'].push( {'host' => 'annex5.example.com', 'path' => '/data/brick6'} )
testcase['test1b'].push( {'host' => 'annex6.example.com', 'path' => '/data/brick6'} )


# XXX: can we hack it with version numbers ?

# this fails because the logical order is different...! can we make this work ?
testcase['test1d'] = []
testcase['test1d'].push( {'host' => 'annex1.example.com', 'path' => '/data/b000001'} )
testcase['test1d'].push( {'host' => 'annex2.example.com', 'path' => '/data/b000001'} )

testcase['test1d'].push( {'host' => 'annex3.example.com', 'path' => '/data/b000002'} )
testcase['test1d'].push( {'host' => 'annex4.example.com', 'path' => '/data/b000002'} )

testcase['test1d'].push( {'host' => 'annex1.example.com', 'path' => '/data/b000003'} )
testcase['test1d'].push( {'host' => 'annex2.example.com', 'path' => '/data/b000003'} )

testcase['test1d'].push( {'host' => 'annex3.example.com', 'path' => '/data/b000004'} )
testcase['test1d'].push( {'host' => 'annex4.example.com', 'path' => '/data/b000004'} )

# and then add:

testcase['test1d'].push( {'host' => 'annex5.example.com', 'path' => '/data/b000005#v0002'} )
testcase['test1d'].push( {'host' => 'annex6.example.com', 'path' => '/data/b000005#v0002'} )

testcase['test1d'].push( {'host' => 'annex5.example.com', 'path' => '/data/b000006#v0002'} )
testcase['test1d'].push( {'host' => 'annex6.example.com', 'path' => '/data/b000006#v0002'} )


tests = testcase.clone	# copy

def get_version_from_path(path)

	rindex = path.rindex('/')
	if rindex.nil?
		# TODO: error, brick needs a / character...
	end
	base = path[rindex+1, path.size-rindex]
	findv = base.rindex('#v')
	if findv.nil?
		return 0	# version 0 (non-existant)
	else
		version = base[findv+2, base.size-findv]
		if version.size < 1
			# TODO: error, version string is missing...
			# TODO: assume version 0 ?
			return -1
		end

		return version.to_i
	end
end

def get_versions(group)
	versions = []
	group.each do |x|
		v = get_version_from_path(x['path'])
		if not versions.include?(v)
			versions.push(v)
		end
	end
	return versions.sort	# should be all int's
end

def filter_version(group, version)

	result = []
	group.each do |x|
		v = get_version_from_path(x['path'])
		if v == version
			result.push(x)
		end
	end
	return result
end

result = {}

# apologies if the ruby is not optimal, i'm a puppet expert, not a ruby pro :P
tests.keys.each do |group|

	# XXX: testing...
	if group != 'test1d'
		next
	end

	tests[group] = tests[group].shuffle	# just to prove the algorithm works...

	vfinal = []	# versioned final
	versions = get_versions(tests[group])	# list of available versions...
	versions.each do |version|

		subset = filter_version(tests[group], version)

		collect = {}

		subset.each do |x|
			key = x['host']
			val = x['path']

			if not collect.has_key?(key)
				collect[key] = []	# initialize
			end

			collect[key].push(val)	# save in array
			# TODO: ensure this array is always sorted (we could also do this after
			# or always insert elements in the correct sorted order too :P)
			collect[key] = collect[key].sort
		end

		# we also could do this sort here...
		collect.keys.each do |x|
			collect[x] = collect[x].sort
		end

		final = []	# final order...
		while collect.size > 0
			collect.keys.sort.each do |x|

				# NOTE: this array should already be sorted!
				p = collect[x].shift	# assume an array of at least 1 element
				final.push( { 'host' => x, 'path' => p } )	# save

				if collect[x].size == 0		# maybe the array is empty now
					collect.delete(x)	# remove that empty list's key
				end

			end
		end
		vfinal = vfinal.concat(final)
	end

	# build final result
	result[group] = vfinal.collect {|x| x['host']+':'+x['path'] }

	if not testcase[group] == vfinal
		puts '# group: ' + group + ' failed!'
		puts testcase[group]
		puts '#'
		puts vfinal
		puts "----------------------------------------------------------------\n"
	else
		puts '# group: ' + group + ' passed!'
	end
end

result.keys.each do |x|
	puts '# group: ' + x
	puts result[x]
	puts "----------------------------------------------------------------\n"
end

#puts result

