_bem_context = {
	_alias_map: {}
	_alias_stacks: {
	},
	known_names: {}
}

bem_debug = false
			
work_stack(stack, callback)
	while length(stack) > 0
		entry = pop(stack)
		if entry != ()
			callback(entry)

set_alias(alias, name)
	if name != null && alias != null
		_bem_context._alias_map[alias] = name
		
lookup_alias(name)
	if name in _bem_context._alias_map
		return _bem_context._alias_map[name]
	else
		return name



store_alias(alias)
	level_name = called-from[1]
	if not level_name in _bem_context._alias_stacks
		_bem_context._alias_stacks[level_name] = () ()
	
	if alias != null
		push(_bem_context._alias_stacks[level_name], alias)
	
pop_last_alias()
	level_name = called-from[1]
	if not level_name in _bem_context._alias_stacks
		return null
	return pop(_bem_context._alias_stacks[level_name])

apply_alias_stack(name, level_name=null)
	if level_name == null
		level_name = called-from[1]
	if level_name in _bem_context._alias_stacks
		work_stack(_bem_context._alias_stacks[level_name], @(element){
			set_alias(element, name)
		})



auto_name(delimiter, caller)
	if delimiter == null
		return caller
	return split(delimiter, caller)[-1]

is_nested(mixin_name=null)
	_free_hits = 0
	if mixin_name == null
		shift(called-from)
		mixin_name = shift(called-from)
	else 
		_free_hits = 1
	for parent in called-from
		if parent == mixin_name
			if _free_hits == 0
				return true
			else
				_free_hits = _free_hits - 1
	return false

is_nested_in(parent_list=null)
	if parent_list == null
		return false
	for  parent in parent_list
		if parent in called-from
			return true
	return false
	
not_nested_in(parent_name)
	return !(parent_name in called-from)
	
is_any_parent_nested()
	//RV-Level RV-Element--modifier RV-Element RV-Block--modifier RV-BreakPoint--horizontal RV-Block--modifier 	RV-Fan--horizontal RV-Block
	for i in (length(called-from)...0)
		i = i - 1
		if i != index(called-from, called-from[i])
			return true
	return false

string_contains(smaller, greater)
	if smaller == null || greater == null
		return true
	
	if length(smaller) > length(greater)
		return false

	for i in range(0, length(smaller) - 1)
		//p(i substr(smaller, i, 1) substr(greater, i, 1))
		if substr(smaller, i, 1) != substr(greater, i, 1)
			return false
	return true

contigious_index(call_stack)
	for i in range(0, length(call_stack) - 1)
		if !string_contains(call_stack[i+1], call_stack[i])
			return i
	return -1
	
filter(list, value_list)
	filtered = ()
	for element in list
		if not (element in value_list)
			push(filtered, element)
	return filtered

RV-Level(name_delimiter, selector_callback, name=null)
	call_stack = split(' ', ''+called-from)

	call_stack = filter(call_stack, ('RV-Level' 'RV-Block' 'RV-Block--modifier' 'RV-Element' 'RV-Element--modifier' 'RV-Modifier'))
	
	mixin_name = call_stack[0]
	if name == null
		name = auto_name(name_delimiter, mixin_name)
	
	cindex = contigious_index(call_stack)
	
	if bem_debug
		--attempt mixin_name
		--cindex cindex
		--nested_in_super_parents nested_in_super_parents
	
	// TODO Clear up this logic
	if cindex != 0
		if name == null
			name = pop_last_alias()
		name = lookup_alias(name)
		apply_alias_stack(name)

		selector_name = selector_callback(name)
		if name == ''
			selector_name = split(name_delimiter, selector_name)[0]
		
		if cindex > 0 && !(name in _bem_context.known_names)
			return
		else
			_bem_context.known_names[name] = name

			define('current_selector', selector_name, true)
			{selector_name}
				{block}
				if bem_debug
					--mixin_name mixin_name
					--name name
	else 
		store_alias(name)
		{block}
		if bem_debug
			--mixin_name mixin_name
			--name name

RV-Block(name=null)
	+RV-Level(null, @(name){
		return '.'+name
	}, name)
		{block}
	if not is_nested('RV-Block')
		_bem_context._alias_map = {}
		_bem_context._alias_stacks = {}
		_bem_context.known_names = {}

		
RV-Block--shorthand(name)
	+RV-Block(name)
		{block}

RV-Element(name=null)
	+RV-Level('__', @(name){
		return '& ^[0]__'+name
	}, name)
		{block}
		
		
RV-Element--modifier(name=null)
	+RV-Level('--', @(name){
		return '&--'+name
	}, name)
		{block}
		
RV-Block--modifier(name=null)
	+RV-Level('--', @(name){
		return '&--'+name
	}, name)
		{block}
