function SelectionList() {
	this.items = new Array();
	this.request = null;
	this.user = null;
	this.date = null;
	this.price = null;
	this.discount = 0;
	this.startupRatingPoints = 0;
	this.onLoad = function() {};
	this.onFailure = function() {};
	
	SelectionList.prototype.load = function(url) {
		Progress.show("Nahrávám konfiguraci...");
		this.request = new AjaxRequest();
		this.request.onSuccess = delegate(this, this.success);
		this.request.onFailure = delegate(this, this.failure);
		this.request.get(url);
	};

	SelectionList.prototype.failure = function() {
		Progress.hide();
		Error.show("Nepodařilo se nahrát konfiguraci.\n" + this.request.responseText);
		this.onFailure();
	};

	SelectionList.prototype.success = function() {
		Progress.hide();
		var document = this.request.responseDocument;
		for (var i = 0; i < document.childNodes.length; i++) {
			this.parse("", document.childNodes[i]);
		}
		// DEBUG
		/*alert(
			"Configuration loaded for\n" +  
			"lastName: " + this.user.lastName + "\n" +
			"phone: " + this.user.phone
		);*/
		// UPDATE : nebude 
		// this.startupRatingPoints = this.getRatingPoints();
		this.onLoad();
	};

	SelectionList.prototype.parse = function(path, node) {
		var attrs = node.attributes;
		switch (path + "/" + node.nodeName) {
		case "/user":	
			var user = new User();
			user.id = AttrReader.asString(attrs, "id");
			user.lastName = AttrReader.asString(attrs, "prijmeni");
			user.phone = AttrReader.asString(attrs, "telcislo");
			this.user = user;
			break;
		case "/ucet":	
			var account = new Account();
			this.user.account = account;
			break;
		case "/ucet/user":	
			this.user.account.userId = AttrReader.asString(attrs, "id");
			this.user.account.userLastName = AttrReader.asString(attrs, "prijmeni");
			this.user.account.userPhone = AttrReader.asString(attrs, "telcislo");
			break;
		case "/ucet/pasmo":	
			this.user.account.tariffName = AttrReader.asString(attrs, "name");
			break;
		case "/ucet/charakter":	
			this.user.account.characterName = AttrReader.asString(attrs, "name");
			break;
		case "/ucet/charakter/sluzby/sluzba":	
			var service = new AccountService();
			service.type = AttrReader.asString(attrs, "typ");
			service.productId = AttrReader.asString(attrs, "produkt_id");
			service.amount = AttrReader.asNumber(attrs, "pocet");
			if (node.firstChild != null) {
				service.name = node.firstChild.nodeValue;
			}
			this.user.account.services.push(service);
			break;
		case "/scenar":	
			this.date = AttrReader.asString(attrs, "datum");
			this.price = AttrReader.asString(attrs, "cena");
			this.discount = AttrReader.asString(attrs, "sleva");
			if (this.discount == null) {
				this.discount = 0;
			}
			break;
		case "/scenar/produkty/produkt":	
			var id = AttrReader.asNumber(attrs, "id");
			var categoryId = AttrReader.asNumber(attrs, "nabidkaid");
			var groupId = AttrReader.asNumber(attrs, "skupinaid");
			var amount = AttrReader.asNumber(attrs, "pocet");
			if (isNaN(groupId)) groupId = 0;
			if (isNaN(categoryId)) categoryId = 0;
			for (var i = 0; i < c.products.items.length; i++) {
				var product = c.products.items[i];
				if (product.id == id && 
				  product.category.id == categoryId &&
				  product.group.id == groupId) {
					product.amount = amount;
					this.add(product);
				}
			}
			break;
		}
		for (var i = 0; i < node.childNodes.length; i++) {
			if (node.childNodes[i].nodeType == 1) {
				this.parse(path + "/" + node.nodeName, node.childNodes[i]);
			}
		}
	};

	SelectionList.prototype.size = function() {
		return this.items.length;
	};

	SelectionList.prototype.add = function(product) {
		this.items.push(product);
	};

	SelectionList.prototype.remove = function(product) {
		var index = -1;
		for (var i = 0; i < this.items.length; i++) {
			if (this.items[i] == product) {
				index = i;
				break;
			}
		}
		if (index > -1) {
			this.items.splice(index, 1);
		}
	};

	SelectionList.prototype.contains = function(product) {
		for (var i = 0; i < this.items.length; i++) {
			if (typeof(product) == "object" && this.items[i] == product ||
				typeof(product) == "number" && this.items[i].id == product) {
				return true;
			}
		}
		return false;
	};

	SelectionList.prototype.validate = function() {
		// UPDATE: reset validate flagu
		for (var i = 0; i < this.items.length; i++) {
			var product = this.items[i];
			product.validated = false;
		}
		// novy typ validace
		// UPDATE: pokud produkt "sparuje", oznaci si to pro pripad dalsi validace
		for (var i = 0; i < c.products.validations.length; i++) {
			var validation = c.products.validations[i];
			var leftCount = 0;
			var rightCount = 0;
			for (var j = 0; j < validation.leftProducts.length; j++) {
				var product = this.findProduct(validation.leftProducts[j]);
				if (product != null) {
					leftCount += product.amount;
				}
			}
			for (var j = 0; j < validation.rightProducts.length; j++) {
				var product = this.findProduct(validation.rightProducts[j]);
				if (product != null) {
					rightCount += product.amount;
				}
			}
			// pravidla validace
			var validated = false;
			if (validation.type == "<") {
				if (!(leftCount < rightCount)) {
					return validation.message;
				}
				validated = true;
			}
			else if (validation.type == "<=") {
				if (!(leftCount <= rightCount)) {
					return validation.message;
				}
				validated = true;
			}
			else if (validation.type == "==") {
				if (!(leftCount == rightCount)) {
					return validation.message;
				}
				validated = true;
			}

			// UPDATE: vse ok, sparovano nebo zadny produkt vybran
			// nastavime flag
			if (validated) {
				for (var j = 0; j < validation.leftProducts.length; j++) {
					var product = this.findProduct(validation.leftProducts[j]);
					if (product != null) {
						product.validated = true;
					}
				}
			}
				
		}
		// validaace <mimo> a <soucasne>
		var result = null;
		for (var i = 0; i < this.items.length; i++) {
			var product = this.items[i];
			if (!product.validated) {
				// FIXME : je to otazka mechaniky, jestli validovat vzdy...
				//product.validated = true;
				for (var j = 0; j < product.mustBe.length; j++) {
					var rule = product.mustBe[j];
					var reference = c.products.find(rule.productId);
					if (!this.contains(reference)) {
						// UPDATE: message je XML specific
						if (rule.message != null) {
							return rule.message;
						}
						else {
							return "Produkt " + product.fullName + " <strong>vyžaduje produkt</strong> " + reference.fullName + ".";
						}
					}
				}
				for (var j = 0; j < product.cantBe.length; j++) {
					var rule = product.cantBe[j];
					var reference = c.products.find(rule.productId);
					if (this.contains(reference)) {
						if (rule.message) {
							return rule.message;
						}
						else {
							return "Produkt " +  reference.fullName + " <strong>nesmí být vybrán společně s produktem</strong> " + product.fullName + ".";
						}
					}
				}
			}
		}
		return result;
	};

	SelectionList.prototype.getProductsCount = function(categoryId) {
		var count = 0;
		for (var i = 0; i < this.items.length; i++) {
			var product = this.items[i];
			if (product.category.id == categoryId) {
				count += product.amount;
			}
		}
		return count;
	};

	SelectionList.prototype.findCategory = function(id) {
		for (var i = 0; i < this.items.length; i++) {
			if (this.items[i].category.id == id) {
				return this.items[i].category;
			}
		}
		return null;
	};

	SelectionList.prototype.findProduct = function(id) {
		for (var i = 0; i < this.items.length; i++) {
			if (this.items[i].id == id) {
				return this.items[i];
			}
		}
		return null;
	};

	SelectionList.prototype.getPriceForCategory = function(id) {
		var price = 0;
		var category = this.findCategory(id);
		if (category == null) {
			return 0;
		}
		var count = this.getProductsCount(id);
		var tariff = null;
		for (var i = 0; i < category.tariffs.length; i++) {
			tariff = category.tariffs[i];
			if (count >= tariff.min && count <= tariff.max) {
				price += tariff.price;
				tariff = null;
				break;
			}
		}
		if (tariff != null) {
			// tarifni pasmo nebylo nalezeno, tak se pouzije 
			// jednotkova cena za kategorii
			price += tariff.price + (count - tariff.max) * category.price;
		}
		return price;
	};
	
	SelectionList.prototype.getStandardPrice = function() {
		var basicPrice = this.getPriceForCategory(Config.basicCategoryId);
		if (basicPrice == 0) {
			basicPrice = Config.minimumPrice;
		}
		var extendedPrice = this.getPriceForCategory(Config.extendedCategoryId);
		return basicPrice + extendedPrice;
	};

	SelectionList.prototype.getStandardPriceDiscounted = function() {
		return this.getStandardPrice() * (100 - this.discount) / 100;
	};

	SelectionList.prototype.getRatingPoints = function() {
		var points = 0;
		// body za Standard
		var basicCategory = c.products.findCategory(Config.basicCategoryId);
		var basicCount = this.getProductsCount(Config.basicCategoryId);
		var basicPoints = 0;
		for (var i = 0; i < basicCategory.ratings.length; i++) {
			var rating = basicCategory.ratings[i];
			if (basicCount >= rating.min) {
				basicPoints = rating.points;
				break;
			}
		}
		// body za Plus
		var extendedCategory = c.products.findCategory(Config.extendedCategoryId);
		var extendedCount = this.getProductsCount(Config.extendedCategoryId);
		var extendedPoints = 0;
		for (var i = 0; i < extendedCategory.ratings.length; i++) {
			var rating = extendedCategory.ratings[i];
			if (extendedCount >= rating.min) {
				extendedPoints = rating.points;
				break;
			}
		}
		// body za Specialy
		var exclusiveCategory = c.products.findCategory(Config.exclusiveCategoryId);
		var exclusivePoints = 0;
		for (var i = 0; i < this.items.length; i++) {
			var product = this.items[i];
			if (product.category.id != Config.exclusiveCategoryId) {
				continue;
			}
			for (var j = 0; j < exclusiveCategory.ratings.length; j++) {
				var rating = exclusiveCategory.ratings[j];
				if (product.id == rating.productId) {
					exclusivePoints += rating.points;
					break;
				}
			}
		}
		return basicPoints + extendedPoints + exclusivePoints;
	};

	SelectionList.prototype.getExclusivePrice = function() {
		var price = 0;
		for (var i = 0; i < this.items.length; i++) {
			var product = this.items[i];
			if (product.category.id != Config.exclusiveCategoryId) {
				continue;
			}
			price += product.amount * product.price;
		}
		return price;
	};

	SelectionList.prototype.getRemainingCount = function(categoryId) {
		var category = c.products.findCategory(categoryId);
		if (category == null) {
			return 0;
		}
		var count = this.getProductsCount(categoryId);
		if (count == 0) {
			if (categoryId == Config.basicCategoryId) {
				return 1;
			}
			else {
				return 0;
			}
		}
		for (var i = 0; i < category.tariffs.length; i++) {
			var tariff = category.tariffs[i];
			if (count >= tariff.min && count <= tariff.max) {
				return tariff.max - count;
			}
		}
		return 0;
	};

	SelectionList.prototype.findGroup = function(id) {
		for (var i = 0; i < this.items.length; i++) {
			if (this.items[i].group.id == id) {
				return this.items[i].group;
			}
		}
		return null;
	};

	SelectionList.prototype.findByCategories = function() {
		var result = new SelectionList();
		for (var i = 0; i < this.items.length; i++) {
			var product = this.items[i];
			for (var j = 0; j < arguments.length; j++) {
				if (product.category.id == arguments[j]) {
					result.add(product);
				}
			}
		}
		return result;
	};

	SelectionList.prototype.getBenefits = function(forSpecial) {
		var result = new Array();
		if (forSpecial && this.items.length == 0) {
			for (var i = 0; i < Config.stickyBenefitsForEmptyExclusive.length; i++) {
				var benefit = new Benefit();
				benefit.text = Config.stickyBenefitsForEmptyExclusive[i];
				result.push(benefit);
			}
			return result;
		}
		if (!forSpecial) {
			// sticky benefits
			for (var i = 0; i < Config.stickyBenefits.length; i++) {
				var benefit = new Benefit();
				benefit.text = Config.stickyBenefits[i];
				result.push(benefit);
			}
		}
		// produktove benefity
		for (var priority = 1; priority <= 3; priority++) {
			for (var i = 0; i < this.items.length; i++) {
				var product = this.items[i];
				for (var k = 0; k < product.benefits.length; k++) {
					var benefit = product.benefits[k];
					var duplicate = false;
					for (var m = 0; m < result.length; m++) {
						if (result[m].id == benefit.id) {
							duplicate = true;
						}
					}
					if (!duplicate && result.length < 6 && benefit.priority == priority) {
						result.push(benefit);
					}
				}
			}
		}
		return result;
	};
	

	SelectionList.prototype.getXML = function() {
		var result = "";
		result += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
		result += "<request>\n";
		if (this.user != null) {
			result += "<user id=\"" + this.user.id + "\" />\n";
		}
		if (this.user != null && this.user.account != null) {
			result += "<ucet>\n";
			result += 	"\t<user id=\"" + this.user.account.userId + "\" />\n";
			result += "</ucet>\n";
		}
		result += 	"\t<scenar cena=\"" + (this.getStandardPrice() + this.getExclusivePrice()) + "\" sleva=\"" + this.discount + "\">\n";
		result += 		"\t\t<produkty>\n";
		for (var i = 0; i < this.items.length; i++) {
			var product = this.items[i];
			result += 		"\t\t\t<produkt id=\"" + product.id + "\" pocet=\"" + product.amount + "\" />\n";
		}
		result += 		"\t\t</produkty>\n";
		result += "\t</scenar>\n";
		result += "</request>\n";
		return result;
	}

}

