﻿/*
 * Obsługa warstwy przykrywającej.
 *
 * Wymagane biblioteki:
 *
 * - jQuery.js (v. 1.4.1)
 *
 * @author Łukasz Świerżewski <lukasz at zirpe dot com>
 * @version 1.0
 */

function Preloader(m_preloader) {

 /*
  * ATRYBUTY:
  */

 var _o_self = this;
 var $_o_preloader;
 var _b_running, _b_stopIfCan, _b_afterFirstLoop;
 var _h_interval;
 var _i_loop;

 var _am_options;
 var _am_defaultOptions = {
  showSpeed: 0,
  hideSpeed: 0,
  stepSpeed: 250,
  callbackBeforeStart: null,
  callbackAfterStart: null,
  callbackAfterFirstLoop: null,
  callbackBeforeStop: null,
  callbackAfterStop: null,
  loopCounter: null,  
  callbackOnStep: null,
  stopCondition: null
 };

 /*
  * METODY PRYWATNE:
  */

 /*
  * Konstruktor.
  *
  * @param mixed Obiekt wykorzystywanego preloadera.
  */
 function _init(m_preloader) {
  _am_options = {};
  _b_running = _b_stopIfCan = _b_afterFirstLoop = false;

  $_o_preloader = $(m_preloader).hide();
 }

 /*
  * Obsługa kolejnego kroku preloadera.
  */
 function _step() {
  if (_am_options.loopCounter && $.isFunction(_am_options.loopCounter)) {
   if (_am_options.loopCounter(_o_self)) _i_loop++;
  } else _i_loop++;

  if (_i_loop == 1 && !_b_afterFirstLoop && _am_options.callbackAfterFirstLoop && $.isFunction(_am_options.callbackAfterFirstLoop)) {
   _b_afterFirstLoop = true;
   _am_options.callbackAfterFirstLoop(_o_self);
  }

  if (_am_options.callbackOnStep && $.isFunction(_am_options.callbackOnStep)) _am_options.callbackOnStep(_o_self);

  if (_canStop()) _o_self.stop();
 }

 /*
  * Sprawdza czy można zatrzymać preloader.
  *
  * @return boolean <i>TRUE</i> jeśli można zatrzymać preloader, <i>FALSE</i> w przeciwnym wypadku.
  */
 function _canStop() {
  return _i_loop > 0 && ((_am_options.stopCondition && $.isFunction(_am_options.stopCondition) && _am_options.stopCondition(_o_self)) || _b_stopIfCan);
 }

 /*
  * METODY PUBLICZNE:
  */

 /*
  * Ustawia ustawienia.
  *
  * @param array Ustawienia.
  * @param boolean Flaga informująca o wyczyszczeniu bieżących ustawień do domyślnych (domyślnie: tak).
  */
 this.setOptions = function(am_options, b_clear) {
  if (b_clear === undefined) b_clear = true;
  _am_options = $.extend({}, b_clear ? _am_defaultOptions : _am_options, am_options);
 };

 /*
  * Zwraca bieżące ustawienia.
  *
  * @return array Bieżące ustawienia.
  */
 this.getOptions = function() {
  return _am_options;
 };
  
 /*
  * Zwraca objekt wykorzystywanego preloadera.
  *
  * @return Object Objekt wykorzystywanego preloadera.
  */
 this.getPreloader = function() {
  return $_o_preloader;
 };

 /*
  * Uruchamia preloader.
  *
  * @return boolean <i>TRUE</i> jeśli preloader został uruchomiony pomyślnie, <i>FALSE</i> w przeciwnym wypadku.
  */
 this.start = function() {
  if (!$_o_preloader || $_o_preloader.length == 0) return false;
 
  if (!_b_running) {
   _i_loop = 0;
   setTimeout(function() { _h_interval = setInterval(_step, _am_options.stepSpeed); }, _am_options.showSpeed);
   _b_running = true;
   _b_stopIfCan = _b_afterFirstLoop = false;
  }

  if (_am_options.callbackBeforeStart && $.isFunction(_am_options.callbackBeforeStart)) _am_options.callbackBeforeStart(_o_self);

  if (_am_options.showSpeed == 0) {
   $_o_preloader.show();
   if (_am_options.callbackAfterStart && $.isFunction(_am_options.callbackAfterStart)) _am_options.callbackAfterStart(_o_self);
  } else {
   $_o_preloader.fadeIn(_am_options.showSpeed, function() {
    if (_am_options.callbackAfterStart && $.isFunction(_am_options.callbackAfterStart)) _am_options.callbackAfterStart(_o_self);
   });
  }

  return true;
 };

 /*
  * Zatrzymuje preloader.
  *
  * @return boolean <i>TRUE</i> jeśli preloader został zatrzymany pomyślnie, <i>FALSE</i> w przeciwnym wypadku.
  */
 this.stop = function() {
  if (!_b_running) return false;

  if (!_canStop()) {
   _b_stopIfCan = true;
   return false;
  }

  if (_am_options.callbackBeforeStop && $.isFunction(_am_options.callbackBeforeStop)) _am_options.callbackBeforeStop(_o_self);

  clearInterval(_h_interval);

  if (_am_options.hideSpeed == 0) {
   $_o_preloader.hide();
   _b_running = _b_stopIfCan = _b_afterFirstLoop = false;
   if (_am_options.callbackAfterStop && $.isFunction(_am_options.callbackAfterStop)) _am_options.callbackAfterStop(_o_self);
  } else {
   $_o_preloader.fadeOut(_am_options.hideSpeed, function() {
    _b_running = _b_stopIfCan = _b_afterFirstLoop = false;

    if (_am_options.callbackAfterStop && $.isFunction(_am_options.callbackAfterStop)) _am_options.callbackAfterStop(_o_self);
   });
  }

  return true;
 };

 /*
  * WYWOŁANIE KONSTRUKTORA:
  */
 _init(m_preloader);

 return this;
};
