
class Pattern:

	cache    = Jsop.data();

	Asset = require "./asset.js";
	Card = require "../card";
	
	constructor( text, type ):
		@.length = 0;
		@.string = text;
		if type == 'Logic':
			@.type = type;
			@.add( Asset.compile( text, 'Logic' ) );
		else:
			while m = Asset.test( text ):
				if m.index:
					@.add( text.slice(0, m.index) );
				@.add(  Asset.compile(m) );
				text = text.substr( m.index + m[0].length );
			if text:
				@.add( text );

	add():
		for asset => arguments:
			if asset as 'string':
				asset = SText.cleanESC( asset );
			@[@.length ++] = asset;
		return @;

	parse(std, node):
		if @.type == 'Logic':
			return @[0].parse(node, std)
		else:
			return parsePattern(@, node, std);

	@::isPattern = true;

	static compile(text, type):
		if cache[text]:
			return cache[text];
		return cache[text] = new Pattern(text, type);

	static parse(std, patt, node):
		if patt as 'string':
			patt = Pattern.compile(patt);
		return patt.parse(std, node);

	function parsePattern(patt, node, std):
		card = new Card( node.isNode ? node.type : 'Clip' );
		for ref => patt:
			if ref.isAsset:
				ref = checkAccAsset(ref, node, std)
				if !ref:
					if card[-1] as 'string':
						ref = card[-1].replace(/\s*(\,|\.|\:\:)*\s*$/, '');
						if !ref:
							Array::pop.call(card);
						else:
							card[-1] = ref;
					continue;
			if ref:
				if ref === true:
					continue;
				card.add( ref );

		if !card.length:
			return "";

		if patt.length == 1 && (patt[0].name == 'LIST'|| patt[0].name == 'EACH'):
			return Jsop.toArray(card);

		if card.length == 1:
			if card.type == card[0].type:
				card = card[0];
			else if patt.length == 1:
				if patt[0].type == 'Call':
					card = card[0];
		return card;

	function checkAccAsset(acc, node, std):
		if ref = acc.parse(node, std):
			if ref.isSyntax || ref.isToken:
				if std.handle.standard == node.type && ref == node:
					ref = std.read(ref, true);
				else:
					ref = std.read(ref);
		else if ref === 0:
			ref = '0';
		return ref;


module.exports = Pattern;