

/*
 This Script includes base classes for parsing CSS Style 
 Strings into objects.
 
 These classes can be used directly to parse CSS, however 
 they may also be inherited from to provide support for
 parsing objects that use similar sintax.
 
*/


/* 
 Base class for a style selector, or collection of selectors
 Format expected is:
 Selector { property: value; property2: value; } ...
*/
if (!SIGI) throw("SIGI.Parsing depends on the following scripts. Please make sure these are included.\nSIGI.js");

SIGI.Parsing = {};

function SelectorParser (selector) {
	this.Base();
	this.styles = new Array();
	if (selector) this.parseStyleSheet(selector);	
};
SelectorParser.inherits(SIGI.Base);
SelectorParser.prototype.parseStyleSheet = function(selector) {
	// split the Styles into individual blocks
	selector = selector.replace(/\n/g, " ");
	var styles = selector.split(/}/);

	for (var i=0; i < styles.length; i++) {
		style = styles[i];
		if (style.length > 0) style += " }";
		var re = new RegExp("^\\s*([^{]+?)\\s*\\{(.*)\\}\\s*$","ig");
		if (re.test(style)) {
			re.exec(style);
			this.styles.push(new SIGI.Parsing.StyleParser(RegExp.$1, RegExp.$2));
		}
	}
};
SIGI.Parsing.SelectorParser = SelectorParser;
SelectorParser = null;

/* 
 Base Class for a Style Object
 
 format expected for selectorsText is:
	Selector, .Selector, #Selector

 format expected for propertiesText is:
	property: value; property: value;
*/
function StyleParser (propertiesText, selectorsText) {
	this.Base();
	this.selectors = new Array();
	
	if (selectorsText) this.parseSelectors(selectorsText);
	if (propertiesText) this.parseProperties(propertiesText);
};
StyleParser.inherits(SIGI.Base);
StyleParser.prototype.addSelector = function(selector) {
	this.selectors.push(selector);
};
StyleParser.prototype.addProperty = function(property, value) {
	if (typeof(property) == "string") {
		property = new SIGI.Parsing.PropertyParser(property, value);
	}
	this.setProperty(property.propertyName, property.value);
};
StyleParser.prototype.setProperty = function(propertyName, value) {
	this[propertyName] = value;
};
StyleParser.prototype.getProperty = function(propertyName) {
	return this[propertyName];
};
StyleParser.prototype.parseSelectors = function(selectorsText) {
	// parse the selectors
	var selectors = selectorsText.split(/\s*,\s*/);

	for (var i=0; i < selectors.length; i++) {
		selector = selectors[i].trim();
		if (selector.length > 0) {
			this.addSelector(selector);
		}
	}
};
StyleParser.prototype.parseProperties = function(propertiesText) {
	// parse the properties
	
	/*	The following template breaks up a list of property:value pairs 
		delimited by a semi-colon. It also allows for semi-colons to be
		embeded in quoted values
	*/
	var template = /\s*([-\w]+)\s*:\s*((?:"[^"]*"|'[^']*'|[^'";])*)\s*(?:;|$)/;
	var properties = template.exec(propertiesText);
	
	while (properties != null) {			
		var property = properties[0];
							
		if (/^\s*([\w\._-]+)\s*:\s*(.*?)\s*$/.test(property)) {
			var propertyName = properties[1];
			var propertyValue = properties[2];	
			this.addProperty(propertyName, propertyValue);
		}
		propertiesText = propertiesText.replace(template, "");
		properties = template.exec(propertiesText);
	}
};
SIGI.Parsing.StyleParser = StyleParser;
StyleParser = null;



function PropertyParser (name, value) {
	this.Base();
	this.name = "";
	this.value = "";
	
	if (name) this.parseName(name.trim());
	if (value) this.parseValue(value.trim());
};
PropertyParser.inherits(SIGI.Base);
PropertyParser.prototype.parseName = function(name) {
	name = name.trim();
	this.name = name;
	
	/*	if the name is hyphenated then	we replace the
		hyphen and capitalize the following letter */		
	if (/[-](\w)/.test(name)) {
		name = name.replace(/[-](\w)/g,function($0,$1) {return $1.toUpperCase()});
	}
	this.propertyName = name;
};
PropertyParser.prototype.parseValue = function(value) {
	this.value = value;
};
SIGI.Parsing.PropertyParser = PropertyParser;
PropertyParser = null;
