/*
 * Klasa obslugujaca wyswietlacz segmentowy. Segmenty sa ze soba powiazane i 
 * np. przekroczenie maksymalnej wartosci w jednym segmencie powoduje 
 * zwiekszenie wartosci segmentu sasiedniego
 */
function SegmentDisplay(_strObjectName,_strDivId)
{
	this.aSegments = null;											//Tablica ze strukturami segmentow
	this.strDivId = _strDivId;										//Id div'a wyswietlacza
	this.strObjectName = _strObjectName;							//Nazwa obiektu wyswietlacza
	this.aImagesArray = null;										//Tablica zawierajaca linki do obrazkow
	this.strLineStyle = '2px solid gray';							//Styl lini oddzielajacej
	this.strLineBorderStyle = '1px solid black';					//Styl lini otaczajacej
	this.strSeparatorStyle = 'font-weight: bold; font-size: 36px;'; //Styl separatora segmentow
	this.objInput = null;											//Obiekt input do którego bedzie wpisywana wartosc wyswietlacza
	this.nImgWidth = 26;												//Szeropkosc jednego obrazka
	this.bFillZeros = true;											//czy domyslnie dla GetString wypelniac pozostale pola zerami
	
	/*
	 * Funkcja dodajaca segment do wyswietlacza
	 *	 
	 * @param string nazwa segmentu @see GetString
	 * @param int wartosc poczatkowa segmentu
	 * @param int wartosc maksymalna segmentu (nigdy nie osiagana)
	 * @param int maksymalna ilosc cyfr w segmencie
	 * @param string separator segmentu
	 * @param bool wymuszanie wypelniania zerami
	 *
	 */
	this.PushBackSegment = function (_strSegName,_nSegValue,_nSegMaxValue,_nSegElementsNum,_nSegSeparator,_bForseFillZeros)
	{
		//Sprawdzamy czy mamy segmenty
		if(!this.aSegments)
			this.aSegments = new Array();
					
		//Ustawianie warotsci poczatkowych
		if(!_nSegSeparator)
			_nSegSeparator = '';
			
		if(!_bForseFillZeros)
			_bForseFillZeros = false;
			
		//Dopisywanie segmentu
		this.aSegments.push(
		{
			strSegName: _strSegName,
			nSegValue: _nSegValue,
			nSegMaxValue: _nSegMaxValue,
			nSegElementsNum: _nSegElementsNum,
			nSegSeparator: _nSegSeparator,
			bForseFillZeros: _bForseFillZeros
		}
		);
	};
	
	/*
	 * Funkcja ustawiacjaca tablice obrazków
	 *	 
	 * @param string nazwa folderu z obrazkami
	 * @param string rozszerzenie plików
	 *
	 */
	this.SetImagesDir = function (_strImageDir,_imgExtensions)
	{
		//Inicjalizacja tablicy
		this.aImagesArray = new Array();
		
		var bPreloadingImagesEnalbled = false;
		var preloadingImageTemp = null;
		
		if(document.images)
			bPreloadingImagesEnalbled = true;
		
		//Wpisywanie klejnych obrazkó do tablicy
		for(i=0;i<10;i++)
		{
			this.aImagesArray.push(new Array(_strImageDir+'/'+i+'t'+_imgExtensions,_strImageDir+'/'+i+'b'+_imgExtensions));
			
			//Jesli ladownia wstepne jest wlaczone
			if(bPreloadingImagesEnalbled)
			{
				preloadingImageTemp = new Image();
				preloadingImageTemp.src = _strImageDir+'/'+i+'t'+_imgExtensions;
				
				preloadingImageTemp = new Image();
				preloadingImageTemp.src = _strImageDir+'/'+i+'b'+_imgExtensions;
				
				if(this.nImgWidth != preloadingImageTemp.width && preloadingImageTemp.width > 0)
					this.nImgWidth = preloadingImageTemp.width;
			}
		}
	};

	/*
	 * Funkcja zwracajaca string z wartoscia wyswietlacza
	 *	 
	 * @param string String formatujacy wyjscie. Segment identyfikuje sie po jego nazwie. 
	 *				Podanie pustego ciagu formatujacego spowoduej sformatowanie y separatorami
	 * @param bool czy wypelniac zerami
	 *
	 * @return string Ciag z wartoscia wyswietlacza
	 */
	this.GetString = function (_strFormatString,_bFillZeros)
	{
		//Sprawdzamy czy mamy segmenty
		if(!this.aSegments)
			return 'NO SEGMENTS';
		
		var strFormatString = '';	
		
		if(_bFillZeros == null)
			_bFillZeros = this.bFillZeros;
		
		//Jesli jest ciag formatujacy
		if(_strFormatString != '')
		{
			strFormatString = _strFormatString;
			
			//Przegladamy segmenty
			for(j=0;j < this.aSegments.length; j++)
			{
				strReplacmentString = this.aSegments[j].nSegValue.toString();
				
				//Wypelnianie zerami
				if(_bFillZeros || this.aSegments[j].bForseFillZeros)
				{
					nZerosCount =  this.aSegments[j].nSegElementsNum - strReplacmentString.length;
					for(i=0; i < nZerosCount ; i++)
						strReplacmentString = '0' + strReplacmentString;
				}
			
				//podminiamy odpowiedni ciag
				regularExpresion = new RegExp(this.aSegments[j].strSegName);
				strFormatString = strFormatString.replace(regularExpresion,strReplacmentString);
			}
		}
		//Gdy niema ciagu formatujacego
		else
		{
			//Przegladamy segmenty
			for(j=0;j < this.aSegments.length; j++)
			{
				strReplacmentString = this.aSegments[j].nSegValue.toString();
				
				//Wypelnianie zerami
				if(_bFillZeros || this.aSegments[j].bForseFillZeros)
				{
					nZerosCount =  this.aSegments[j].nSegElementsNum - strReplacmentString.length;
					for(i=0; i < nZerosCount ; i++)
						strReplacmentString = '0' + strReplacmentString;
				}
			
				//Dopisujemy wartosc segmentu
				strFormatString += strReplacmentString + this.aSegments[j].nSegSeparator;
			}
		}
		
		return strFormatString;
	};
		
	/*
	 * Funkcja ustawia wartosc na podstawie ciagu
	 *
	 * @param string ciag z ktorego mamy wyciagnac wartosc
	 */
	this.SetString = function (_strToSet)
	{
		//Sprawdzamy czy w ogole ustawiono parametr
		if(_strToSet == null)
			return;
			
		var strLastSeparator = '';
		var valToSet = 0;
			
		//Przegladamy segmenty
		for(j=0;j < this.aSegments.length; j++)
			this.aSegments[j].nSegValue = 0;
			
		//Przegladamy segmenty
		for(j=0;j < this.aSegments.length; j++)
		{
			//Jesli jest separator
			if(this.aSegments[j].nSegSeparator)
			{
				strArray = _strToSet.split(this.aSegments[j].nSegSeparator);

				if(strLastSeparator == '.')
					valToSet = parseInt(strArray[0],10)*(Math.pow(10,this.aSegments[j].nSegElementsNum - strArray[0].length));
				else
					valToSet = parseInt(strArray[0],10);
					
				if(valToSet >= this.aSegments[j].nSegMaxValue)
					valToSet = this.aSegments[j].nSegMaxValue - 1;
				
				this.aSegments[j].nSegValue = valToSet;
				
				_strToSet = strArray[1];
				
				strLastSeparator = this.aSegments[j].nSegSeparator;
			}
			//Jesli nie ma separatora
			else
			{
				if(_strToSet)
				{
					if(strLastSeparator == '.')
					{
						modyfier = Math.round((Math.pow(10,this.aSegments[j].nSegElementsNum - _strToSet.length)));
						if(modyfier <= 0)
							modyfier = 1;
							
						valToSet = parseInt(_strToSet,10)*modyfier;
					}
					else
						valToSet = parseInt(_strToSet,10);
						
					if(valToSet >= this.aSegments[j].nSegMaxValue)
					{
						temp = this.aSegments[j].nSegElementsNum;
						val = valToSet.toString().substr(0,temp);
						valToSet = parseInt(val);
					}
					
					this.aSegments[j].nSegValue = valToSet;
				}
				
				break;
			}
		}
	};
	
	/*
	 * Funkcja zmieniajaca wartosc segmentu o zadana wartosc
	 *	 
	 * @param int indeks segmentu w ktorym zmieniamy warotsc
	 * @param int wartosc o jaka zmieniamy warotsc segmentu
	 *
	 * @return bool Prawde jesli sa segmenty, falsz jesli ich brak
	 */
	this.SegmentChange = function (_nSegmentNum,_nChangeBy)
	{
		//Sprawdzamy czy mamy segmenty
		if(!this.aSegments)
			return false;
			
		//Zmieniamy wartosc segmentu
		this.aSegments[_nSegmentNum].nSegValue += _nChangeBy;
		
		//Sprawdzamy czy nie przekroczono maksymalnej warotsci
		if(this.aSegments[_nSegmentNum].nSegValue >= this.aSegments[_nSegmentNum].nSegMaxValue)
		{
			//Sprowadzamy wartosc segmentu do dopuszczalnej warotsci
			this.aSegments[_nSegmentNum].nSegValue %= this.aSegments[_nSegmentNum].nSegMaxValue;
			
			//Zmieniamy poprzedni segment
			if(_nSegmentNum > 0)
				this.SegmentChange(_nSegmentNum - 1,1);
		}
		
		//Jesli warotsc sie zmniejszyla
		if(this.aSegments[_nSegmentNum].nSegValue < 0)
		{
			this.aSegments[_nSegmentNum].nSegValue = this.aSegments[_nSegmentNum].nSegMaxValue + this.aSegments[_nSegmentNum].nSegValue;
			
			//Zmieniamy poprzedni segment
			if(_nSegmentNum > 0)
				this.SegmentChange(_nSegmentNum - 1,-1);
		}
		
		return this.RenderDisplay();
	};
	
	/*
	 * Funkcja rysujaca wyswietlacza w divie
	 *
	 * @return bool True jesli sa segmenty, false jesli ich brak
	 */
	this.RenderDisplay = function ()
	{
		//Sprawdzamy czy mamy segmenty
		if(!this.aSegments || !this.aImagesArray)
			return false;
			
		//Zmienne
		var strOut = "";
		
		//Przegladamy segmenty
		for(j=0;j < this.aSegments.length; j++)
		{
			//Zmienne
			aSegmentTemp = new Array();
		
			//Wyliczamy czesci
			nTemp = this.aSegments[j].nSegValue;

			for(k=0;k<this.aSegments[j].nSegElementsNum;k++)
			{
				aSegmentTemp[k] = Math.floor(nTemp / Math.pow(10,this.aSegments[j].nSegElementsNum-k-1));
				nTemp -= aSegmentTemp[k] * Math.pow(10,this.aSegments[j].nSegElementsNum-k-1);
			}
			
			//Rysowanie
			for(i=0;i<this.aSegments[j].nSegElementsNum;i++)
			{
				nChangeBy = Math.pow(10,this.aSegments[j].nSegElementsNum-1-i);
				strOut += '<td style="cursor: pointer;border: '+this.strLineBorderStyle+';width:'+this.nImgWidth+'px;"><img src="'+this.aImagesArray[aSegmentTemp[i]][0]+'" onMouseDown="'+this.strObjectName+'.SegmentChange('+j+','+nChangeBy+');return false;" style="border-bottom: '+this.strLineStyle+';"/><br /><img src="'+this.aImagesArray[aSegmentTemp[i]][1]+'" onMouseDown="'+this.strObjectName+'.SegmentChange('+j+','+(-1*nChangeBy)+');return false;" /></td>';
			}
			
			//Sprawdzanie czy jest separator
			if(this.aSegments[j].nSegSeparator != '')
				strOut += '<td style="'+this.strSeparatorStyle+'">'+this.aSegments[j].nSegSeparator+'</td>';
		}
	
		//Wrzucanie wygenerowanego wyswietlacza do div'a
		document.getElementById(this.strDivId).innerHTML = '<table border="0" cellspacing="0" cellpadding="0"><tr>'+strOut+'</tr></table>';

		//Updatujemy wartosc w inpucie, jezeli taki jest
		if(this.objInput)
			this.objInput.value = this.GetString('');
		
		return true;
	};
		
	/*
	 * Funkcja tworzy powiazanie z obiektem typu input w formularzu, wpisujac do niego aktualna warotsc wyswietlacza
	 *
	 * @param object obiekt typu input
	 */
	 this.CreateAssociationWithInput = function (_objInput)
	 {
	 	//Sprawdzamy czy obiekt istnieje
	 	if(_objInput && _objInput.tagName == 'INPUT')
	 	{
	 		this.objInput = _objInput;
	 		this.objInput.value = this.GetString('');
	 	}
	 };
	
	
	return this;
};

/*
 * Klasa bazujaca na klasie SegmentDisplay, wstawiajaca wyswietlacz segmentowy w okienko popup
 */
function PopUpSegmentDisplay(_strObjectName)
{
	this.strObjectName = _strObjectName;	//Nazwa obiektu wyswietlacza
	this.strPopupDivId = '';				//Id obiektu popup
	this.objDisplay = null;					//Obiekt SegmentDisplay
	this.objInnerHtmlId = null;				//Id obiektu do którego wpisywana jest warosc wyswietlacza
	
	//Metody klasy bazowej
	this.PushBackSegment = null;
	this.SetImagesDir = null;
	this.GetString = null;
	this.SegmentChange = null;
	this.RenderDisplay = null;
	this.CreateAssociationWithInput = null;

	/*
	 * Funkcja inicjalizuje wyswietlacz
	 */
	this.Init = function ()
	{
		//Tworzymy obiekt podstawowego wyswietlacza
		this.objDisplay = new SegmentDisplay(_strObjectName+'.objDisplay',_strObjectName+'_displayDiv');
		
		//Tworzymy popup'a dla wyswietlacza
		this.CreatePopupForDisplay(_strObjectName);
		
		//Przepisujemy pola
		this.strLineStyle = this.objDisplay.strLineStyle;
		this.strSeparatorStyle = this.objDisplay.strSeparatorStyle;
		this.strLineBorderStyle = this.objDisplay.strLineBorderStyle;
		this.nImgWidth = this.objDisplay.nImgWidth;
		this.bFillZeros = this.objDisplay.bFillZeros;
		
		//Przepusjemy metody
		this.PushBackSegment = this.objDisplay.PushBackSegment;

		this.SetImagesDir = this.objDisplay.SetImagesDir;

		this.GetString =this.objDisplay.GetString;

		this.SegmentChange = this.objDisplay.SegmentChange;

		this.RenderDisplay = this.objDisplay.RenderDisplay;

		this.CreateAssociationWithInput = this.objDisplay.CreateAssociationWithInput;
		
		this.SetString = this.objDisplay.SetString;
	};
	
	/*
	 * Funkcja tworzy div'y dla wyswietlacza
	 *
	 * @param string nazwa bazowa divów dla wyswietlacza
	 */
	this.CreatePopupForDisplay = function(_strDivName)
	{
		//Sprawdzamy czy div istnieje
		if(!document.getElementById(_strDivName))
		{
			//Zapisywanie id div'ow
			this.strPopupDivId = _strDivName+'_popupDiv';
			this.strDivId = _strDivName+'_displayDiv';
			
			//Tworzymy obrazek przycisku zamykajacego
			imgClose = document.createElement('img');
			imgClose.src = 'gfx/close.gif';
			imgClose.onmousedown = function(){eval(this.alt);};//eval('function(){'+this.strObjectName+'.HidePopup();};');
			imgClose.align = 'right';
			imgClose.style.cursor = 'pointer';
			imgClose.title = "Zamknij";
			imgClose.alt = this.strObjectName+'.HidePopup();';//
			
			//Tworzymy div'a popup'a
			popUpDiv = document.createElement('div');
			popUpDiv.id = this.strPopupDivId;
			popUpDiv.zIndex = 30;
			popUpDiv.className = 'popupInfo';
			popUpDiv.style.position = 'absolute';
			popUpDiv.style.left = '0px';
			popUpDiv.style.top = '0px';
			popUpDiv.style.width = '140px';
			popUpDiv.style.height = '43px';
			popUpDiv.style.padding = '2px';
			popUpDiv.style.display = 'none';
			
			//Tworzymy div'a wyswietlacza
			displayDiv = document.createElement('div');
			displayDiv.id = this.strDivId;
			
			//Dodajemy div'a wyswietlacza do div'a popup'a
			popUpDiv.appendChild(imgClose);
			popUpDiv.appendChild(displayDiv);
			
			//Dodajemy diva
			document.body.appendChild(popUpDiv);
		
		}
	};
		
	/*
	 * Funkcja chowajaca popup'a
	 */
	this.HidePopup = function ()
	{
		//Sprawdzamy czy zainicjalizowany
		if(document.getElementById(this.strPopupDivId))
		{
			document.getElementById(this.strPopupDivId).style.display = 'none';
			
			if(this.objInnerHtmlId)
	 			document.getElementById(this.objInnerHtmlId).innerHTML =  this.GetString('');
		}
	};
	
	/*
	 * Funkcja pokazujaca popup'a
	 *
	 * @param int wspolrzedna x gdzie ma sie pojawic popup
	 * @param int wspolrzedna y gdzie ma sie pojawic popup
	 */
	this.ShowPopup = function (_nX,_nY)
	{
		//Sprawdzamy czy zainicjalizowany
		if(document.getElementById(this.strPopupDivId))
		{
			document.getElementById(this.strPopupDivId).style.left = _nX + 'px';
			document.getElementById(this.strPopupDivId).style.top = _nY + 'px';
			
			this.RenderDisplay();
			
			document.getElementById(this.strPopupDivId).style.display = 'block';
		}
	};
	
	/*
	 * Funkcja tworzy powiazanie z obiektem typu input w formularzu, wpisujac do niego aktualna warotsc wyswietlacza
	 *
	 * @param object obiekt typu input
	 */
	 this.CreateObjinnerHTMLAssociation = function (_objInnerHtmlId)
	 {
	 	//Sprawdzamy czy obiekt istnieje
	 	if(_objInnerHtmlId)
	 	{
	 		this.objInnerHtmlId = _objInnerHtmlId;
	 		document.getElementById(this.objInnerHtmlId).innerHTML =  this.GetString('');
	 	}
	 };
	
	/*
	 * Funkcja uaktualnia szerokosc popup'a dla wyswietlacza
	 */
	this.UpdateWidth = function()
	{
		if(document.getElementById(this.strPopupDivId))
		{
			var nSegElementsNum = 0;
			var nSeparatorsNum = 0;
			
			//Przegladamy segmenty
			for(i=0;i < this.aSegments.length; i++)
			{
				nSegElementsNum += this.aSegments[i].nSegElementsNum;
				if(this.aSegments[i].nSegSeparator != '')
					nSeparatorsNum++;
			}
			
			document.getElementById(this.strPopupDivId).style.width = nSegElementsNum*(this.nImgWidth+2)+nSeparatorsNum*10+20+"px";
		}
	};
	return this;
};

/*
 * Funkcja tworzy standardowy zegar z godzina i minutami
 *
 * @param string nazwa zmiennej zegara
 * @param string id obiektu (np. span'a) do ktorej wpisywana jest warotsc
 * @param object obiekt input w ktorym trzymamy wartosc
 * @param int wartosc poczatkowa godzin
 * @param int wartosc poczatkowa minut
 */
function CreatePopUpClock(_strNazwaZmiennjZegara,_strSpanWartosci, _objInput,_nGodziny,_nMinuty)
{
	//Jesli podana nazwa zmiennej
	if(!_strNazwaZmiennjZegara || _strNazwaZmiennjZegara == '')
		return null;
	
	//Ustawiamy defaultowe wartosc
	if(!_nGodziny)
		_nGodziny = 00;

	if(!_nMinuty)
		_nMinuty = 00;
		
	//Tworzymy zegar
	newClock = new PopUpSegmentDisplay(_strNazwaZmiennjZegara);
			
	//Inicjalizujemey zegar
	newClock.Init();
		
	//Ustawiamy zrodlo obrazkow
	newClock.SetImagesDir('gfx/digits/big','.gif');
	
	//Tworzymy segmenty zegara
	newClock.PushBackSegment('godziny',_nGodziny,24,2,':');
	newClock.PushBackSegment('minuty',_nMinuty,60,2);
			
	//Przypiusjemy span'a
	if(_strSpanWartosci)
		newClock.CreateObjinnerHTMLAssociation(_strSpanWartosci);
		
	//Przypisujemy obiekt typu input
	if(_objInput)
		newClock.CreateAssociationWithInput(_objInput);

	return newClock;
}

/*
 * Funkcja tworzy wyswietlacz segmentowy dla liczby zmienno przecinkowej
 *
 * @param string nazwa zmiennej liczby
 * @param string id obiektu (np. span'a) do ktorej wpisywana jest warotsc
 * @param object obiekt input w ktorym trzymamy wartosc
 * @param int maksymalna liczba cyfr w czesci calkowitej
 * @param int maksymalna liczba cyfr w czesci ulamkowej
 * @param float wartosc poczatkowa
 */
function StworzLiczbe(_strVarName,_strSpanName,_objInput,_nMaxLenCalkowita,_nMaxLenUlamkowa,_fWartosc)
{
	//Sprawdzamy czy podano wymagana parametry
	if(!_strVarName)
		return null;
		
	//Tworzymy segmenty
	var nowaLiczba = new PopUpSegmentDisplay(_strVarName);
	
	//Inicjalizujemey zegar
	nowaLiczba.Init();
	
	//Ustawiamy wypelnienie zerami
	nowaLiczba.bFillZeros = false;
	
	//Ustawianie obrazkow
	nowaLiczba.SetImagesDir('gfx/digits/big','.gif');
	
	//Tworzenie segmentu
	_cSeparator = '';
	if(_nMaxLenUlamkowa != null && _nMaxLenUlamkowa > 0)
		_cSeparator = '.';
	nowaLiczba.PushBackSegment('calkowite',0,Math.pow(10,_nMaxLenCalkowita),_nMaxLenCalkowita,_cSeparator);
	
	if(_nMaxLenUlamkowa != null && _nMaxLenUlamkowa > 0)
		nowaLiczba.PushBackSegment('ulamkowe',0,Math.pow(10,_nMaxLenUlamkowa),_nMaxLenUlamkowa,'',true);
		
	//Aktualizacja szerokosci popup'a
	nowaLiczba.UpdateWidth();
	
	//Sprawdzamy wartosc poczatkowa
	_fWartosc = parseFloat(_fWartosc);
	
	if(isNaN(_fWartosc))
		_fWartosc = 0.0;
	
	nowaLiczba.SetString(_fWartosc.toString());
	
	//Przypiusjemy span'a
	if(_strSpanName)
		nowaLiczba.CreateObjinnerHTMLAssociation(_strSpanName);
		
	//Przypisujemy input'a
	if(_objInput)
		nowaLiczba.CreateAssociationWithInput(_objInput);
		
	return nowaLiczba;
}
