/**
 * @author stefan.schult
 */

(function(){
	if(typeof console == 'undefined'){
		window['console'] = {};
	};
	if(typeof console.debug == 'undefined'){
		window['console'].debug = function(){
			if(typeof console.log == 'undefined'){
//				var d = "";
//				for(var i = 0; i<arguments.length; i++){
//					d+= arguments[i] + "\n";
//				}
//				alert(d);
			}
			else console.log(arguments);
		};
	}
}());

/* Validator scripts */
var checkAvailabilityObj = {
	availabilityValidation : {
		validFunc: function(){
			var v = (!this._product || (this._product.available.isAvailable()));
			return {isValide: v, message: {text: "availabilityValidation", overwrite: ["_all"]}};
		},
		message: function(){return localizations.availabilityValidation;}
	}
};

var checkAmoungObj = {
	minOrderValidation : {
		validFunc: function(){
			var v = (!this._product || ((this._product.minOrder == 0) && isNaN(this.$elements['$amountField'].value)) || (this._product.minOrder <= this.$elements['$amountField'].value));
			if(v && isNaN(this.$elements['$amountField'].value)){
				this.$elements['$amountField'].value = 1;
			}
			return {isValide: v, message: {text:  "minOrderValidation", value: (!!this._product) ? this._product.minOrder : ""}};
		},
		message: function(){return localizations.minOrderValidation;}
	},
	maxOrderValidation : {
		validFunc: function(){
			return {isValide: (!this._product || (this._product.maxOrder >= this.$elements['$amountField'].value)), message: {text: "maxOrderValidation", value: (!!this._product) ? this._product.maxOrder : ""}};
		},
		message: function(){return localizations.maxOrderValidation;}
	}
};

var checkVariationObj = {
	variationHasValueValidation : {
		validFunc: function(){
			return {isValide: (this.$elements['$variationField'] && this.$elements['$variationField'].value != ""), message: {text: "variationHasValueValidation", overwrite: ["minOrderValidation", "maxOrderValidation"]}};
		},
		message: function(){return localizations.variationHasValueValidation;}
	}
};

var checkSizeObj = {
	sizeHasValueValidation : {
		validFunc: function(){
			return {isValide: (this.$elements['$sizeField'] && this.$elements['$sizeField'].value != ""), message: {text: "sizeHasValueValidation", overwrite: ["minOrderValidation", "maxOrderValidation"]}};
		},
		message: function(){return localizations.sizeHasValueValidation;}
	}
};

var Validator = Class.create({
	initialize: function() {
		this.showMessages = {};
		this.validations = {};
		this.messages = {};
	},
	setValidations: function(valiValues) {
		for (var key in valiValues) {
			this.validations[key] = valiValues[key].validFunc;
			this.messages[key] = valiValues[key].message();
		}
	},
	set$Elements: function(elements) {
		this.$elements = elements;
	},
	validationsObject: function() {
		var product = this.product;
		var $elements = this.$elements;
		return Object.extend({_product: product, "$elements": $elements }, this.validations);
	},
	isValide: function(key) {
		return this.validations[key].call(this.validationsObject()).isValide;
	},
	getMessage: function(key) {
		return this.validations[key].call(this.validationsObject());
	},
	showAllMessages: function() {
		var mess = {};
		var overwriteAll = null;
		for (var key in this.showMessages) {
			var m = this.showMessages[key];
			if (m.overwrite != null && m.overwrite.length > 0) {
				if(m.overwrite[0] == "_all"&& !overwriteAll) {
					overwriteAll = {};
					overwriteAll[key] = this.messageToHtml(key, m.message);
				};
				for (var i = 0; i < m.overwrite.length; i++) {
					delete mess[m.overwrite[i]];
				}
			}
			mess[key] = this.messageToHtml(key, m.message);
		}
		if(overwriteAll != null){
			this.output(overwriteAll);
		} else {
			this.output(mess);
		}
	},
	output: function(messages) {
		try {
			var box = this.$elements['$errorMessageBoxArea'];
			if (box != null) {
				box.childElements().each(function(ele){
					ele.remove();
				});
			} else {
				box = new Element("div", {'class' : 'errorMessageBox'});
				this.$elements['rootForm'].insert({before: box});
			}
			for (var key in this.showMessages) {
				box.insert(messages[key]);
			}
		} catch(ex){}
	},
	buildMessage: function(t, v) {
		return t.replace(/###value###/, v);
	},
	messageToHtml: function(k, m) {
		return new Element("p", {'class': "errorMessage "+k}).insert(new Element("strong").update(m));
	},
	showMessages: null,
	isAllValide: function(valideFunction) {
		var isValide = true;
		this.showMessages = {};
		for (var key in this.validations) {
			var cur = this.getMessage(key);
			isValide = isValide && cur.isValide;
			if (!cur.isValide) {
				this.showMessages[key] = {message: this.buildMessage(this.messages[cur.message.text], cur.message.value), overwrite: cur.message.overwrite};
			}
		}
		valideFunction(isValide);
		return isValide;
	},
	setProduct: function(product) {
		this.product = product;
	},
	validations: null,
	messages: null,
	product: null,
	$elements: {}
});

/**
 * @class ElementCollection
 * @description Collection of DOM-Elements
 */
var ElementCollection = Class.create({
	initialize: function(){
		this.elements = {};
	},
	/**
	 * add a dom-element
	 * @param key
	 * @param elementId
	 * @param doNotCheck if true throw an error when dom-element not available
	 */
	add: function(key, elementId, doNotCheck){
		if(!doNotCheck && !$(elementId))
			throw 'Unkown Element ' + elementId + "[" + key + "]";
		this.elements[key] = elementId;
	},
	/**
	 * get a dom-element
	 * @param key
	 * @param doNotCheck if true throw an error when dom-element not available
	 */
	getElement: function(key, doNotCheck){
		var r = this.elements[key];
		if(!doNotCheck && typeof r == "undefined")
			throw 'Unkown Element ' + key;
		return $(this.elements[key]);
	},
	elements: null
});

/**
 * @class PpCore
 */
var PpCore = Class.create({
	initialize: function(){

	},
	/**
	 * set a collection of dom-elements
	 * @param elementsCollection
	 */
	setElements: function(elementsCollection){
		this.elements = elementsCollection;
	},
	/**
	 * get an object with prototype-dom-elements
	 */
	get$Elements: function(){
		var retValue = {};
		for(var key in this){
			if (key.indexOf("$") == 0) {
				try {
					retValue[key] = this[key]();
				} catch(ex){};
			}
		}
		return retValue;
	},
	/**
	 * disable a link on an a-tag
	 * @param ele
	 * @param resetHref
	 */
	disableHref : function(ele, resetHref) {
		if(ele) {
			//Event.observe(ele, 'click', function(){ return false; }); //IE
			ele.setAttribute('onclick', 'return false;'); //FF
			ele.onclick = function(){ //IE!
				return false;
			};
			ele.setAttribute('target', '');
			if(resetHref) {
				ele.setAttribute("defaultHref", ele.href);
				ele.href = "javascript:void(0);";
			}
		}
	},
	/**
	 * Debug output
	 */
	debug: function(){
		var r = "Debug\n--- --- ---\n";
		for(var key in this){
			var v = Object.isFunction(this[key]) ? "function()" : typeof this[key] == "object" ? "object{}" :  this[key];
			r+=key+" : "+v+"\n";
		}
		return r;
	}
});

/**
 * @class VariantCollection
 * @description Collection of Variants
 */
var VariantCollection = Class.create({
	initialize: function(){
		this.products = {};
		this.productsArray = [];
	},
	/**
	 * add a productvariant
	 * @param product
	 */
	add: function(product){
		var k1 = null;
		if(this.productsArray.length == 0){
			this.equalPrice = product.prize;
		}
		if(!product.v1)
			k1 = 0;
		else
			k1 = product.v1;
		var k2 = null;
		if(!product.v2)
			k2 = 0;
		else
			k2 = product.v2;
		if(!this.products[k1]) {
			this.products[k1] = {};
			this.products[k1][0] = product;
		}
		this.products[k1][k2] = product;
		this.productsArray.push(product);
		this.setHasEqualPrices(product.prize);
		this.setLowestPrize(product.prize, product.prizeString, k1);
		this.setHighestPrize(product.prize, product.prizeString, k1);
		this.length++;
	},
	/**
	 * get first productvariant of the collection
	 */
	getFirstProduct: function(){
		return this.productsArray[0];
	},
	/**
	 * get an productvariant
	 * @param k1
	 * @param k2
	 */
	getProduct: function(k1, k2){
		try {
			if(!!k1 && k1 !="" && !!k2 && k2 !=""){
				return this.products[k1][k2];
			}
			if(!!k1 && k1 !="" && !k2){
				return this.products[k1][0];
			}
			if(!k1 && k1 != "" && !k2){
				return this.productsArray[0];
			}
			throw "Cant find product!";
		}catch(ex){
			return null;
		}
	},
	/**
	 * get an array of productvariants
	 * @param k1
	 */
	getProducts: function(k1){
		if(!k1)
			return this.productsArray;
		var r = [];
		for(var key in this.products[k1]){
			if(key != 0)
				r.push(this.products[k1][key]);
		}
		return r;
	},
	/**
	 * is an equalprice
	 * @param prize
	 */
	setHasEqualPrices: function(prize){
		this.hasEqualPrices = this.hasEqualPrices && (this.equalPrice == prize);
		this.needPrizeStarting = !this.hasEqualPrices;
	},
	setHighestPrize: function(prize, prizeString, k2){
		if(k2 != null){
			var key = "highestPrize_" + k2;
			if(this[key] == null || this[key].value < prize)
				this[key] = {value: prize, text: prizeString};
		}
		if(this.highestPrize == null || this.highestPrize.value < prize)
			this.highestPrize = {value: prize, text: prizeString};
	},
	setLowestPrize: function(prize, prizeString, k1){
		if(k1 != null){
			var key = "lowestPrize_" + k1;
			if(this[key] == null || this[key].value > prize) {
				if(this[key] == null && (this['lowestPrize__color'] == null || this['lowestPrize__color'].value > prize))
					this['lowestPrize__color'] = {value: prize, text: prizeString};
				this[key] = {value: prize, text: prizeString};
			}
		}
		if(this.lowestPrize == null || this.lowestPrize.value > prize)
			this.lowestPrize = {value: prize, text: prizeString};
	},
	getHighestPrize: function(){
		return this.highestPrize;
	},
	getLowestPrize: function(k){
		if(k != null && k != "") {
			return this['lowestPrize_' + k];
		}
		if(k == "" || k == null)
			return this.lowestPrize;
	},
	products: null,
	productsArray: null,
	highestPrize: null,
	lowestPrize: null,
	length: 0,
	hasEqualPrices: true,
	needPrizeStarting: true,
	equalPrice: 0
});

/**
 * @class ProductVariant
 * @description Variant of a product
 */
var ProductVariant = Class.create(PpCore, {
	initialize: function(v1, v2){
		this.v1 = v1;
		this.v2 = v2;
	},
	$prizeArea: function(){return this.elements.getElement('prizeArea');},
	$orderNumberArea: function(){return this.elements.getElement('orderNumberArea');},
	$availIconArea: function(){return this.elements.getElement('availIconArea');},
	$toAskTheArticle: function(){return this.elements.getElement('toAskTheArticle');},
	v1: null,
	v2: null,
	available: null,
	prize: null,
	oldPrize: null,
	prizeString: "",
	oldPrizeString: "",
	orderNr: null,
	minOrder: 0,
	maxOrder: 0,
	pk: "",
	/**
	 * builds dom-elements to show prize
	 * @return prototype dom-element
	 */
	getPrizeHTML: function(){
		var t = this;
		var rootId = this.$prizeArea().id;
		var p = new Element("p",{"id":rootId});
		if(t.oldPrize != null && t.oldPrizeString != ""){
			p;
			var strike = new Element("strike").update(t.oldPrizeString);
			var oldPrize = new Element("span", {"class": "oldPrize"}).update(localizations.prizeInsteadof).insert(strike);
			p.insert(oldPrize);
		}
		if(t.prize != null && t.prizeString != ""){
			var prize = new Element("strong").update(t.prizeString);
			p.insert(prize);
		}
		return p;
	},
	/**
	 * builds dom-elements to show the availibility
	 * @return prototype dom-element
	 */
	getAvailableHTML: function(){
		var t = this.available;
		var rootId = this.$availIconArea().id;
		var div = new Element("div", {"class" : t.id});
		div.insert(new Element("img", {"src": t.image}));
		div.insert(new Element("span").update(t.text));
		return new Element("div", {"id": rootId}).insert(div);
	},
	/**
	 * builds dom-elements to show the ordernumber
	 * @return prototype dom-element
	 */
	getOrderNrHTML: function(){
		var t = this;
		var rootId = this.$orderNumberArea().id;
		var p = new Element("p", {"id": rootId}).update(localizations.orderNumber);
		p.insert(new Element("span", {"id": "bestNrSpan"}).update(t.orderNr));
		return p;
	},
	/**
	 *
	 * @return boolean
	 */
	changeToAskTheArticleHref: function(){
		try {
			var linkStr = this.$toAskTheArticle().href.substr(0,this.$toAskTheArticle().href.lastIndexOf("/")+1);
			this.$toAskTheArticle().href = linkStr + this.orderNr;
			return true;
		} catch(ex){
			return false;
		}
	},
	/**
	 * replaces dom-elements with builded dom-elements
	 */
	buildHTML: function(){
		this.$orderNumberArea().replace(this.getOrderNrHTML());
		this.$prizeArea().replace(this.getPrizeHTML());
		this.$availIconArea().replace(this.getAvailableHTML());
		this.changeToAskTheArticleHref();
		return true;
	}
});

/**
 * Class for the availability of a product or productvariant
 */
var Availability = Class.create({
	initialize: function(whichInt){
		var availables = this.getAvailables();
		this.state = whichInt;
		switch(whichInt){
			case 1: ;
			case 2:
				this.text = availables.available.text;
				this.image = availables.available.src;
				this.id = 'verfuegbar';
				this.state = 2;
				break;
			case 3: ;
			case 4:
				this.text = availables.shortOfStock.text;
				this.image = availables.shortOfStock.src;
				this.id = 'knapp';
				this.state = 4;
				break;
			case 5: ;
			case 6: ;
			default:
				this.text = availables.outOfStock.text;
				this.image = availables.outOfStock.src;
				this.id = 'vergriffen';
				this.state = 6;
				break;
		}
	},
	isAvailable: function(){
		return (this.state != 0 && this.state != 5 && this.state != 6);
	},
	getAvailables: function(){
		return availablesObj;
	},
	/**
	 * preloads an image
	 * @param src
	 */
	loadImg: function(src){
		var img = new Image();
		img.src = src;
		return img;
	},
	state: 0
});

/**
 * @class AbstractDetail
 * @description AbstractClass for Detail
 */
var AbstractDetail = Class.create(PpCore, {
	$rootForm: function(){return this.elements.getElement('rootForm');},
	$pkField: function(){return this.elements.getElement('pkField');},
	$amountField: function(){return this.elements.getElement('amountField');},
	$toShoppingList: function(){return this.elements.getElement('toShoppingList', true);},
	$errorMessageBoxArea: function(){return this.elements.getElement('errorMessageBoxArea');},
	initialize: function(elements){
		this.setElements(elements);
		this.validator = null;
		this.$rootForm().onsubmit = this.checkForm.bindAsEventListener(this);
		if(!!this.$toShoppingList()){
            this.disableHref(this.$toShoppingList(), true);
			this.$toShoppingList().observe("click", this.checkForm.bindAsEventListener(this));
		}
	},
	setPkElementValue: function(pkValue){
		this.$pkField().value = pkValue;
	},
	setProducts: function(products){
		this.products = products;
	},
	validator: null,
	getProduct: function(){
		return this.products.getProduct();
	},
	updateView: function(){
		this.updateProduct();
	},
	updateProduct: function(){
		var p = this.getProduct();
		try {
			this.setPkElementValue(p.pk);
			p.setElements(this.elements);
			p.buildHTML();

		} catch(ex){
		}
	},
	resetProduct: function(){
		var p = this.products.getFirstProduct();
		p.setElements(this.elements);
		//console.debug(p);
		this.setPkElementValue("");
		var t = this;
		this.$prizeArea().replace(this.getFromPrizeHTML());
//		this.$orderNumberArea().replace(new Element('p', {'id': t.$orderNumberArea().id}));
		this.$orderNumberArea().replace(p.getOrderNrHTML());
		this.$availIconArea().replace(new Element('div', {'id': t.$availIconArea().id}));
		this.resetErrors();
	},
	resetErrors: function(){
		var t = this;
		this.$errorMessageBoxArea().replace(new Element('div', {'id': t.$errorMessageBoxArea().id}));
	},
	setValidations: function(){
		this.validator.setValidations(checkAmoungObj);
		this.validator.setValidations(checkAvailabilityObj);
	},
	checkForm: function(event){
        if(!event) var event = {"type": "undefined"};
		this.validator = new Validator();
		this.validator.setProduct(this.getProduct());
		this.validator.set$Elements(this.get$Elements());
		this.setValidations();
        switch(event.type){
			case "click": this.validator.isAllValide(this.toShoppingCartForm.bind(this));
            break;
			default: this.validator.isAllValide(this.submitForm.bind(this));
		}
		return false;
	},
	submitForm: function(isValide){
		if(!isValide){
			this.validator.showAllMessages();
		} else {
			this.$rootForm().submit();
		}
	},
	toShoppingCartForm: function(isValide){
       	if(!isValide){
			this.validator.showAllMessages();
		} else {
			 var pk = this.getProduct().pk;
			 var a = this.$amountField().value;
             document.location = this.$toShoppingList().getAttribute("defaultHref") +"/"+pk+"/"+a;
             return false;
		}
	},
	products: null
});

/**
 * @class DetailAmount
 * @description when only amount on Page
 */
var DetailAmount = Class.create(AbstractDetail, {
});

/**
 * @class DetailAmountAndVariation
 * @description when amount and variation on Page
 */
var DetailAmountAndVariation = Class.create(DetailAmount, {
	$variationField: function(){return this.elements.getElement('variationField');},
	$prizeArea: function(){return this.elements.getElement('prizeArea');},
	$orderNumberArea: function(){return this.elements.getElement('orderNumberArea');},
	$availIconArea: function(){return this.elements.getElement('availIconArea');},
	$errorMessageBoxArea: function(){return this.elements.getElement('errorMessageBoxArea');},
	initialize: function($super, elements){
		$super(elements);
		this.$variationField().observe('change', this.changedVariationField.bindAsEventListener(this))
	},
	changedVariationField: function(){
		this.updateView();
	},
	getProduct: function(){
		return this.products.getProduct(this.$variationField().value);
	},
	getFromPrize: function(){
		return this.products.getLowestPrize('_color');
	},
	getFromPrizeHTML: function(){
		if(this.products.hasEqualPrices && !this.products.needPrizeStarting){
			return this.products.getProduct().getPrizeHTML();
		} else {
			var rootId = this.$prizeArea().id;
			var p = new Element("p",{"id":rootId});
			var prize = new Element("strong").update(((this.products.needPrizeStarting) ? localizations.prizeStarting : "") + this.getFromPrize().text);
			return p.insert(prize);
		}
	},
	updateView: function($super){
		var p = this.getProduct();
		if(typeof p != "undefined" && p != null)
			this.updateProduct();
		else {
			this.resetProduct();
		}
		this.resetErrors();
	},
	setValidations: function($super){
		$super();
		this.validator.setValidations(checkVariationObj);
	}
});

/**
 * @class DetailAmountVariationAndSize
 * @description when amount, variation and size on Page
 */
var DetailAmountVariationAndSize = Class.create(DetailAmountAndVariation, {
	$sizeField: function(){return this.elements.getElement('sizeField');},
	initialize: function($super, elements){
		$super(elements);
		this.$sizeField().observe('change', this.changedSizeField.bindAsEventListener(this));
	},
	setOptionsForSizeField: function(optionsCollection){
		this.optionsForSizeField = optionsCollection;
	},
	changedVariationField: function($super){
		this.fillSizeField();
		$super();
	},
	changedSizeField: function(){
		this.updateView();
	},
	getFromPrize: function(){
		if(this.$variationField().value == ""){
			return this.products.getLowestPrize();
		} else {
			return this.products.getLowestPrize(this.$variationField().value);
		}
	},
	getProduct: function(){
		if(this.$variationField().value != '' && this.$sizeField().value != '') {
			return this.products.getProduct(this.$variationField().value,this.$sizeField().value);
		} else if(this.$variationField().value != '') {
			return this.products.getProduct(this.$variationField().value);
		}
	},
	fillSizeField: function(){
		if(this.$sizeField().nodeName == "INPUT"){
			return false;
		};
		var setOtionsSizeField = function(prod){
			var addText = (!prod.available.isAvailable()) ? localizations.variantNotAvailable : "";
			this.$sizeField().options[this.$sizeField().options.length] = new Option(prod.v2+addText, prod.v2, false, false);
		};
		var defaultOpt = this.$sizeField().options[0];
		this.$sizeField().options.length = 0;
		if(!this.$sizeField().disabled)
			this.$sizeField().options[0] = defaultOpt;
		if(this.$variationField().value != ""){
			var prods = this.products.getProducts(this.$variationField().value);
			prods.each(setOtionsSizeField.bind(this));
		};
		if(this.$sizeField().disabled){
			this.updateView();	
		};
		return true;
	},
	updateView: function($super){
		this.resetProduct();
		if(this.$variationField().value != "" && this.$sizeField().value != "") {
			this.updateProduct();
		} else {
			var t = this;
			this.updateProduct();
			this.fillSizeField();
			this.$availIconArea().replace(new Element('div', {'id': t.$availIconArea().id}));
		}
	},
	setValidations: function($super){
		$super();
		this.validator.setValidations(checkSizeObj);
	},
	optionsForSizeField: null
});

function setPreviewImagesClick(id){
	var p = $(id);
	if(p != null){
		var as = p.select("a");
		as.each(function(item){
			item.observe("click", function(event){
				as.each(function(a){
					a.removeClassName("activeOne");
				});
				this.addClassName("activeOne");
			});
		});
	}
}
setPreviewImagesClick("previewImages");