/**
 * ./out/lascana/src/lca_variantContentHandler.class.js
 * @author Bjoern Simon Lange <bjoern.lange@twt.de>, 31.10.2009
 * @package out
 * @subpackage lascana
 * @version $id$
 */

/**
 * Aktualisierung der Artikelinformationen bei einer Variantenaktion.
 *
 * Vorraussetung fuer diese Klasse ist eingebundenes jQuery.
 * @author Bjoern Simon Lange <bjoern.lange@twt.de>, 31.10.2009
 * @package out
 * @subpackage lascana
 * @param String sFetchingUrl wo koennen die JSON - Daten fuer die Varianten abgerufen werden?
 * @version $id$
 */
function LCA_VariantContentHandler(sFetchingUrl)
{
	/**
	 * Mapping der Imagenamen auf Element - IDs.
	 * @access private
	 * @var Array
	 */
	var aImgMap = new Array();

	/**
	 * Mapping von Element-Selektoren auf OXID-Felder aus dem JSON-Objekt die geaendert werden sollen.
	 * @access private
	 * @var Array
	 */
	var aContentChangeMap = new Array();

	/**
	 * Diese Elemente sollen ihre Sichtbarkeit in Abhaengigkeit von der Varianten Auswahl aendern.
	 * @access private
	 * @var Array
	 */
	var aOnChangeVisibilityMap = new Array();

	/**
	 * Diese Eigenschaft gibt an ob das JSON noch geladen werden muss.
	 * @access private
	 * @var bool
	 */
	var bLoaded = false;

	/**
	 * Objekt zum erweiterten Wechseln von Detailbildern.
	 * @access private
	 * @var Object
	 */
	var oImageSlider = null;

	/**
	 * Die Daten der moeglichen Varianten als JSON-Objekt.
	 * @access private
	 * @var Object
	 */
	var oJsonData = null;

	/**
	 * Klasseninstanz zur Sichtbarkeit in privaten Methoden.
	 * @access private
	 * @var VariantContentHandler
	 */
	var oSelf = this;

	/**
	 * Unter dieser URL koennen die Content-Informationen der Varianten abgerufen werden.
	 * @access private
	 * @var String
	 */
	var sFetchUrl = sFetchingUrl;

	/**
	 * Basis-URL fuer Bilder.
	 * @access private
	 * @var String
	 */
	var sImgBaseUrl = '';

	/**
	 * Prefix der OXID-Feldnamen.
	 *
	 * Entfernen der Redundanz dies in den Methoden per Hand manuell aufzurufen.
	 * @access private
	 * @var String
	 */
	var sOxidFieldPrefix = 'oxarticles__';

	/**
	 * Setzt einen Helper um die Detailbilder durchzuwechseln.
	 * @access public
	 * @return void
	 */
	this.addDetailImgSlider = function(oDetailImageSlider)
	{
		oImageSlider = oDetailImageSlider;
	}; // function

	/**
	 * Mapping Element - IDs auf OXID-Feldnamen.
	 * @access public
	 * @param String sElementSelector Der CSS-Selektor um das Bildelement zu finden.
	 * @param String sOxidField Den Feldnamen von OXID.
	 * @return void
	 * @see aImgMap
	 */
	this.addImgMapping = function(sElementSelector, sOxidField)
	{
		aImgMap[sOxidField] = sElementSelector;
	}; // function

	/**
	 * Sichtbarkeitseinstellungen fuer die Varianten-Auswahl festlegen.
	 * @access public
	 * @param String sElementSelector Der CSS-Selektor um das Element zu finden.
	 * @param Integer iVisibleSince Ab welchen Select-Index soll das Einblenden erfolgen.
	 * @param Integer iVisibleTill Bis zu welchem Index ist dieses Element sichbar?
	 * @return void
	 * @see aOnChangeVisibilityMap
	 */
	this.addOnChangeVisibilityElement = function(sElementSelector, iVisibleSince, iVisibleTill)
	{
		//alert(new Array(iVisibleSince, iVisibleTill === undefined ? null : iVisibleTill));
		aOnChangeVisibilityMap[sElementSelector] = new Array(iVisibleSince, iVisibleTill === undefined ? null : iVisibleTill);
	}; // function

	/**
	 * Welche Elemente sollen mit welchen Daten auf dem letzten Select geaendert werden?
	 * @access public
	 * @param String sElementSelector Der CSS-Selektor um das Bildelement zu finden.
	 * @param String sOxidField Den Feldnamen von OXID.
	 * @param Integer iSelectIndex Auf welchen Select-Index soll die Aktualisierung erfolgen.
	 * @return void
	 * @see aContentChangeMap
	 */
	this.addTextChangeMapping = function(sElementSelector, sOxidField, iSelectIndex)
	{
		if (typeof aContentChangeMap[iSelectIndex] === 'undefined')
		{
			aContentChangeMap[iSelectIndex] = new Array();
		} // if

		aContentChangeMap[iSelectIndex][sElementSelector] = sOxidField;
	}; // function

	/**
	 * Aendert die Bilder aus dem Bildmapping aImgMap.
	 * @access public
	 * @param String sArticleId Der Key im JSON-Objekt.
	 * @return void
	 * @see aImgMap
	 */
	this.changeImages = function(sArticleId)
	{
		fillJsonIfRequired();

		for (sOxidField in aImgMap)
		{
			oElement  = $(aImgMap[sOxidField]);

			if (oJsonData && typeof oElement !== 'undefined')
			{
				try
				{
					oElement.attr('src', sImgBaseUrl + oJsonData[sArticleId][sOxidFieldPrefix + sOxidField]);

					if (oImageSlider && (typeof oImageSlider['changeImageData'] === 'function'))
					{
						oImageSlider.changeImageData(oJsonData[sArticleId]);
					} // if
				} // try
				catch (oExc)
				{
				} // catch
			} // if
		} // for

		if (typeof aContentChangeMap[1] === 'undefined')
		{
			processChangesForSimpleMap(aContentChangeMap[1], sArticleId);
		} // if
	}; // function

	/**
	 * Aendert das href-Attribut des uebergebenen Linkobjekts mit den Daten aus dem uebergebenen String.
	 * @access public
	 * @param Object oLinkObject Linkobjekt.
	 * @param String sNewLink Der neue Link.
	 * @return void
	 */
	this.changeLinkFromText = function(oLinkObject, sNewLink)
	{
		oLinkObject.attr('href', sNewLink);
	}; // function

	/**
	 * Aendert den Wert des entsprechenden Select-Feldes mit den Daten des Artikels der ueber sTarget angegeben wurde.
	 * @access public
	 * @param Object oSelect Das Select-Menue.
	 * @param String sTarget Die Artikel-ID welche das Ziel darstellt.
	 * @return void
	 */
	this.changeSelectValue = function(oSelect, sTarget)
	{
		if (oSelect)
		{
			var aOptions = oSelect.children();

			if (aOptions)
			{
				var iCount = aOptions.size();

				for (iRound = 0; iRound < iCount; iRound++)
				{
					if (aOptions[iRound].value == sTarget)
					{
						oSelect.attr('selectedIndex', iRound);
						oSelect.trigger('change');

						return true;
					} // if
				} // for
			} // if
		} // if

		return false;
	}; // function

	/**
	 * Laedt das JSON-Datenobjekt per AJAX.
	 * @access public
	 * @param boolean bWithSync Asynchrones (false) oder synchrones (true) Laden.
	 * @return void
	 */
	this.fillJson = function(bWithSync)
	{
		if (!bLoaded)
		{
			bLoaded = true;

			// TODO Was passiert wenn der AJAX-Request fehlschlaegt?! Markierung fuer Wartezeit anzeigen.
			$.ajax({
				async: (!bWithSync),
				dataType: 'json',
				success: function(oData, status)
				{
					oJsonData = oData;
				}, // function
				url: sFetchUrl
			});
		} // if
	}; // function

	/**
	 * Kontrolliert ob das JSON-Objekt geladen wurde und holt dieses falls nicht.
	 * @access private
	 * @return void
	 * @see oJsonData, oSelf
	 */
	var fillJsonIfRequired = function()
	{
		if (oJsonData === null)
		{
			oSelf.fillJson(true);
		} // if
	}; // function

	/**
	 * Callback fuer die Reaktion auf die Aenderung des ersten Select-Menues.
	 * @access public
	 * @author Bjoern Simon Lange <bjoern.lange@twt.de>
	 * @author Pascal Streichert <pascal.streichert@twt.de>
	 * @param Integer iSelectCount Wieviele Selects gibt es menschlich gezaehlt insgesamt.
	 * @param Integer iUsedIndex Welches Select nutzen wir grad, maschinengezaehlter Index ab 0.
	 * @param Object oSelect Das ausgewaehlte Select.
	 * @return void
	 */
	this.handleSelect = function(iSelectCount, iUsedIndex, oSelect)
	{
		fillJsonIfRequired();

		if (typeof aContentChangeMap[iUsedIndex + 1] !== 'undefined')
		{
			processChangesForSimpleMap(aContentChangeMap[iUsedIndex + 1], $(oSelect[oSelect.selectedIndex]).attr('value'));
		} // if

		toggleVisibility(iUsedIndex, oSelect);
	}; // function

	/**
	 * Callback fuer die Reaktion auf die Aenderung des ersten Select-Menues.
	 * @access public
	 * @param Object oSelect
	 * @return void
	 */
	this.handleSelectLevel1 = function(oSelect)
	{
		return this.changeImages($(oSelect[oSelect.selectedIndex]).attr('value'));
	}; // function

	/**
	 * Updatet die Elemente die als Key in der Map angegeben sind mit den Felder aus dem JSON-Objekt eines Artikels.
	 * @access private
	 * @param Array aMap Assoziatives "Array", Key sind die Elementselektoren und die Values sind die OXID-Felder.
	 * @param String sArticle Die Artikel-ID.
	 * @return boolean
	 */
	var processChangesForSimpleMap = function(aMap, sArticleId)
	{
		var oData = oJsonData[sArticleId];

		if (typeof oData === 'undefined')
		{
			return false;
		} // if

		for (sSelector in aMap)
		{
			var oElement = $(sSelector);

			if (!oElement.size())
			{
				continue;
			} // if

			var sField = aMap[sSelector];
			var mValue = oData[sField];

			if (typeof mValue === 'undefined')
			{
				mValue = oData[sOxidFieldPrefix + sField];
			} // if

			if (oElement.attr('src') !== undefined)
			{
				oElement.attr('src', mValue);
			} // if
			else if (oElement.attr('href') !== undefined)
			{
				oElement.attr('href', mValue);
			} // elseif
			else
			{
				oElement.html(mValue);
			} // else
		} // for

		return true;
	}; // function

	/**
	 * Setzt die Basis-URL fuer Bilder.
	 * @access public
	 * @param String sUrl
	 * @return void
	 * @see sImgBaseUrl
	 */
	this.setProductImgBaseUrl = function(sUrl)
	{
		sImgBaseUrl = sUrl;
	}; // function

	/**
	 * Aendert die Sichtbarkeit von den festgelegten Elementen.
	 * @access private
	 * @param Integer iIndex Ab welchen Select-Index soll das Einblenden erfolgen.
	 * @param Object oUsedSelect Welches Select wurde gerade betaetigt.
	 * @return void
	 * @author Pascal Streichert <pascal.streichert@twt.de>
	 * @author Bjoern Simon Lange <bjoern.lange@twt.de>
	 */
	var toggleVisibility = function(iIndex, oUsedSelect)
	{
		// Ist das aktuelle Element auf "leer" resettet z.B. mit "Cup waehlen" als Wert, so nimm den vorherigen Zustand an.
		if ($(oUsedSelect[oUsedSelect.selectedIndex]).attr('value') === '')
		{
			--iIndex;
		} // if

		for (var sElement in aOnChangeVisibilityMap)
		{
			var oElement = $(sElement);

			if (oElement.size())
			{
				// Sichtbarmachen des Elements, wenn sich der aktuelle Index in der einschließlichen Range der Sichtbarkeit befindet.
				if (iIndex >= aOnChangeVisibilityMap[sElement][0] && ((aOnChangeVisibilityMap[sElement][1] === null) || (iIndex <= aOnChangeVisibilityMap[sElement][1])))
				{
					oElement.show();
				} // else if
				else
				{
					oElement.hide();
				} // else
			} // if
		} // for
	}; // function
} // class