var Application = {
  _globals: $H({}),

  ajaxResponseProcess: function(transport, messageObject) {
    var response = transport.responseText.evalJSON();
    if (response.authenticationRequired != undefined && response.authenticationRequired) {
      this.ajaxAuthenticationRequired();
      return false;
    }
    if (messageObject !== null && response.message != undefined && response.message != [] && response.message != '') {
        try {
          messageObject.set(response.message);
        } catch (e) {
          try {
            Application.message.set(response.message);
          } catch (e) {
            alert(response.message);
          }
        }
    }
    if (response.error == undefined) {
      return false;
    }
    return response;
  },

  ajaxAuthenticationRequired: function() {
    alert('auth req');
  },

  domReady: Element.observe.curry(document, 'dom:loaded'),

  setMessageController: function(container) {
    Application.message = new SimpleMessage(container);
    Event.observe(document, 'message:set', function(event) {
        Application.message.set(event.memo.message);
    });
  },

  onLoginStatusChangedRegister: function(func) {
    if (typeof this.onLoginStatusChangedActions == 'undefined') {
      this.onLoginStatusChangedActions = $A({});
    }
    this.onLoginStatusChangedActions.push(func);
    return true;
  },

  onLoginStatusChanged: function() {
    if (typeof this.onLoginStatusChangedActions == 'undefined') {
      return;
    }
    this.onLoginStatusChangedActions.each(function(func) {
      func();
    });
  }
};
Event.observe(document, 'application:loginStatusChanged', Application.onLoginStatusChanged.bind(Application));


/**
 * SimpleMessage
 */
var SimpleMessage = Class.create({
  initialize: function(container, options) {
    if (! $(container)) {
      return;
    }
    if (! $(container).id) {
      $(container).identify();
    }
    this.container = $(container);
    this.key = Math.round(Math.random() * 1000000);
    this.last_id = 0;
    this.timeouts = $A([]);
    this.timeoutTime = 2000;
    this.options = options || {};

    SimpleMessage.instances.set($(container).id, this);
  },

  clear: function() {
    this.clearTimeouts();
    this.container.descendants().invoke('stopObserving');
    this.container.update();
    this.container.hide();
  },

  clearTimeouts: function() {
    this.timeouts.each(function(item, index) {
      clearTimeout(this.timeouts[index]);
    }, this);
    this.timeouts.clear();
  },

  add: function(message) {
    if (this.options.add) {
      this.options.add.call(this, message);
      return;
    }
    this.last_id++;
    var _last_id = this.last_id;
    this.container.insert(
      new Element('div', {id: 'message[' + this.key + ']id_' + _last_id}).addClassName('simple-message').update(message));
      this.container.pulsate({ pulses: 2, duration: 1.5 });

    this.container.show();
    this.timeouts[_last_id] = setTimeout(function () {
      try {
        $('message[' + this.key + ']id_' + _last_id).removeClassName("simple-message").addClassName("simple-message-viewed");
      } catch (e) {}
    }.bind(this), this.timeoutTime);
  },

  set: function(message) {
    this.clear();
    if (typeof(message) == 'string') {
      this.add(message);
    } else if (typeof(message) == 'object' && message.length) {
      $A(message).each(this.add, this);
    }
    return true;
  },

  remove: function(message_id) {
    try {
      $('message[' + this.key + ']id_' + message_id).remove();
    } catch (e) {}
    if (this.timeouts[message_id]) {
      clearTimeout(this.timeouts[message_id]);
    }
    if (this.container.immediateDescendants().size() === 0) {
      this.container.hide();
    }
  }
});

var SimpleModalMessage = Class.create({
  initialize: function(opt) {
    this.reset();
    this.options = {
       modalClassName: '',
       closeLink: true,
       width: '',
       padding: 10,
       margin: 10,
	   formatMessage: function() {
	    return this.messages.join('<br />');
	   }
    };
    this.options = Object.extend(Object.clone(this.options), opt || {});
  },

  reset: function() {
    this.messages = $A([]);
  },

  add: function(message) {
    this.messages.push(message);
      new Dialog({
            className: this.options.modalClassName,
            width:this.options.width,
            padding:this.options.padding,
            margin:this.options.margin,
            content:this.options.formatMessage.bind(this),
            close:{
              link:this.options.closeLink,
              overlay:true,
              esc:true
            },
            onClose: this.reset.bind(this)
           }).open();
  },

  set: function(message) {
      this.reset();
      this.add(message);
    return true;
  }
});

Object.extend(SimpleMessage, {
  instances: $H({}),
  getInstance: function(container) {
    if (! $(container)) {
      return;
    }
    if (! $(container).id) {
      $(container).identify();
    }
    var instance = SimpleMessage.instances.get($(container).id);
    return instance !== undefined ? instance : new SimpleMessage(container);
  }
});



var dateFromatISORegexp = /(\d{4})\-(\d{2})\-(\d{2}) (\d{2}):(\d{2}):(\d{2})/;
var dateFromatISO = 'Y-m-d H:i:s';

// Simulates PHP's date function
Date.prototype.format = function(format) {
    var returnStr = '';
    var replace = Date.replaceChars;
    for (var i = 0; i < format.length; i++) {
        var curChar = format.charAt(i);
        if (replace[curChar])
        returnStr += replace[curChar].call(this);
    else
        returnStr += curChar;
    }
    return returnStr;
};

Date.replaceChars = {
    shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    longMonths: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
    shortDays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    longDays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],

    // Day
    d: function() { return (this.getDate() < 10 ? '0' : '') + this.getDate(); },
    D: function() { return Date.replace.shortDays[this.getDay()]; },
    j: function() { return this.getDate(); },
    l: function() { return Date.replace.longDays[this.getDay()]; },
    N: function() { return this.getDay() + 1; },
    S: function() { return (this.getDate() % 10 == 1 && this.getDate() != 11 ? 'st' : (this.getDate() % 10 == 2 && this.getDate() != 12 ? 'nd' : (this.getDate() % 10 == 13 && this.getDate() != 1 ? 'rd' : 'th'))); },
    w: function() { return this.getDay(); },
    z: function() { return "Not Yet Supported"; },

    // Week
    W: function() { return "Not Yet Supported"; },

    // Month
    F: function() { return Date.replace.longMonths[this.getMonth()]; },
    m: function() { return (this.getMonth() < 11 ? '0' : '') + (this.getMonth() + 1); },
    M: function() { return Date.replace.shortMonths[this.getMonth()]; },
    n: function() { return this.getMonth() + 1; },
    t: function() { return "Not Yet Supported"; },

    // Year
    L: function() { return "Not Yet Supported"; },
    o: function() { return "Not Supported"; },
    Y: function() { return this.getFullYear(); },
    y: function() { return ('' + this.getFullYear()).substr(2); },
    // Time

    a: function() { return this.getHours() < 12 ? 'am' : 'pm'; },
    A: function() { return this.getHours() < 12 ? 'AM' : 'PM'; },
    B: function() { return "Not Yet Supported"; },
    g: function() { return this.getHours() === 0 ? 12 : (this.getHours() > 12 ? this.getHours() - 12 : this.getHours()); },
    G: function() { return this.getHours(); },
    h: function() { return (this.getHours() < 10 || (12 < this.getHours() < 22) ? '0' : '') + (this.getHours() < 10 ? this.getHours() + 1 : this.getHours() - 12); },
    H: function() { return (this.getHours() < 10 ? '0' : '') + this.getHours(); },
    i: function() { return (this.getMinutes() < 10 ? '0' : '') + this.getMinutes(); },
    s: function() { return (this.getSeconds() < 10 ? '0' : '') + this.getSeconds(); },

    // Timezone
    e: function() { return "Not Yet Supported"; },
    I: function() { return "Not Supported"; },
    O: function() { return (this.getTimezoneOffset() < 0 ? '-' : '+') + (this.getTimezoneOffset() / 60 < 10 ? '0' : '') + (this.getTimezoneOffset() / 60) + '00'; },
    T: function() { return "Not Yet Supported"; },
    Z: function() { return this.getTimezoneOffset() * 60; },

    // Full Date/Time
    c: function() { return "Not Yet Supported"; },
    r: function() { return this.toString(); },
    U: function() { return this.getTime() / 1000; }
};

/**
 * Remote script include
 */
var ScriptInclude = Class.create({
  initialize: function (sources, callback) {
    if (Application._globals.get('includedExternals') === undefined) {
      Application._globals.set('includedExternals', $H({}));
    }

    this.sources = $A((typeof(sources) == 'string' ? [sources] : sources));
    this.callback = callback || Prototype.emptyFunction;

    if (this.includeOnce === true) {
      this.sources = this.sources.findAll(function (item) {
        return (Application._globals.get('includedExternals').get(item) === undefined);
      });
    }
    this.queueStart();
  },

  queueStart: function() {
    if (this.sources.size() === 0) {
      this.callback();
      return;
    }

    var scriptURL = this.sources.shift();
    if (! this.includeOnce) {
      scriptURL += (scriptURL.indexOf('?') == -1 ? '?' : '&') + 'scriptIncludeTS=' + new Date().getTime();
    }

    var newScript = this._createElement(scriptURL);
    $$('head').shift().appendChild(newScript);
    var callback = arguments.callee.bind(this);

    if (document.addEventListener) {
      if (Prototype.Browser.WebKit || Prototype.Browser.Opera) {
        var iframe = new Element('iframe', {src: scriptURL}).setStyle({display: 'none'});
        $$('body').first().insert(iframe);
        Event.observe(iframe, 'load', callback);
      } else {
        Event.observe(newScript, 'load', callback);
      }
    } else {
      newScript.onreadystatechange = function() {
        if (newScript.readyState == 'complete' || newScript.readyState == 'loaded') {
          newScript.onreadystatechange = null;
          callback();
        }
      };
    }
  },

  _createElement : function(url) {
    return new Element('script', {language: 'javascript', type: 'text/javascript', src: url});
  }
});

/*
ScriptIncludeOnce = new Class.create(ScriptInclude.prototype, {includeOnce: true});
StyleInclude = new Class.create(ScriptInclude, {
    includeOnce: true,
    _createElement : function(url) {
        return new Element('link', {id:'titi', rel: 'stylesheet', type: 'text/css', href: url});
    }
});
*/


var SimpleAjaxForm = Class.create({
  initialize: function(form, options) {
    this.form = $(form);

    this.options = {
      message: window.message,
      formAction: this.form.readAttribute('action') || '',
      formMethod: 'post',
      onBeforeSubmit: function() {},
      onAfterSubmit: function() {},
      onResponseReceived: function() {},
      customCallback: function() {},
      labelErrorClassName: 'flderr',
      inputErrorClassName: 'inputerr',
      listenForMessages: false,
      parameters: {}
    };

    Object.extend(this.options, options || {});

    this.form.stopObserving();
    this.form.observe('submit', this.submitEvent.bindAsEventListener(this));
    if (this.options.listenForMessages) {
        this.form.observe('message:set', this.messageEvent.bindAsEventListener(this));
    }
    this.fixFormAction();
  },

  destroy: function() {
    this.form.descendants.invoke('stopObserving');
    this.form.stopObserving();
  },

  setAction: function (action) {
    this.options.formAction = action;
    this.fixFormAction();
  },

  fixFormAction: function() {
    var bkpEle = this.form.down('input[name="action"]');
    if (bkpEle) {
      document.body.appendChild(bkpEle);
    }
    this.form.writeAttribute('action', this.options.formAction);
    if (bkpEle) {
      this.form.appendChild(bkpEle);
    }
  },

  submitEvent: function(event) {
    event.stop();
    this.options.onBeforeSubmit();
    this.submit();
    this.options.onAfterSubmit();
  },

  submit: function(parameters, callback) {
    if (this.form.isSubmiting) {
      return;
    }
    this.clearRequiredStyle();
    this.form.isSubmiting = true;

    this.form.request({
      method: this.options.formMethod,
      parameters: Object.extend(this.options.parameters, parameters || {}),
      onComplete: function(transport) {
          var response = Application.ajaxResponseProcess(transport, this.options.message);
          this.options.onResponseReceived(response);
          this.form.isSubmiting = false;
          if (! response) {
            return;
          }

          if (response.required) {
            $A(response.required).each(this.setInputAsRequired.bind(this));
          }
          if (response.error) {
            return;
          }

          if (typeof callback == 'function') {
            callback.call(this, response);
          } else {
            this.options.customCallback.call(this, response);
          }
        }.bind(this)
    });
  },

  messageEvent: function(event)
  {
    event.stop();
    if (event.memo.message) {
      this.options.message.set(event.memo.message);
    }
  },

  setInputAsRequired: function(fieldId) {
    try {
        this.form.select('label#' + fieldId + 'Label').shift().addClassName(this.options.labelErrorClassName);
        $(fieldId).addClassName(this.options.inputErrorClassName);
    } catch (e) {}
  },

  clearRequiredStyle: function() {
    this.form.select('label').invoke('removeClassName', this.options.labelErrorClassName);
    this.form.select('.inputerr').invoke('removeClassName', this.options.inputErrorClassName);
  }
});

// obiect care afiseaza un modal pentru blocarea interfetei
window.simpleUIBlocker = {
  builded: false,
  IE6: (Prototype.Browser.IE && parseInt(navigator.appVersion) == 4 && navigator.userAgent.toLowerCase().indexOf('msie 6.') != -1),
  isBlocking: false,
  defaultMessage: '<div style="text-align:center;background:#fff; padding:10px;"><h1>Asteptati...</h1><img src="/img/admin/loading.gif" width="31" height="31"></div>',
  timeout: null,
  window: null,
  autoclose: true,

  block: function(message, time) {
    message = message || this.defaultMessage;
    clearTimeout(this.timeout);
    this.timeout = setTimeout(this.launchBlock.bind(this, message), (time || 0.2) * 1000);
  },

  launchBlock: function(message) {
    if (! this.builded) {
      this.createElements();
    }

    this.overlay.show();
    this.content.show();
    this.content.update(message);
    this.fixDimensions();

    if (this.IE6) {
      Event.observe(window, 'scroll', function() {
          this.fixScroll();
      }.bind(this));
    }

    Event.observe(window, 'resize', function() {
        this.fixDimensions();
    }.bind(this));

    clearTimeout(this.timeout);
    // programat singur sa se inchida dupa 10 secunde, in caz de erori
    if (this.autoclose) {
    	this.timeout = setTimeout(this.unblock.bind(this), 10000);
    }
  },

  unblock: function() {
    clearTimeout(this.timeout);
    if (! this.builded) {
      return;
    }

    this.overlay.stopObserving();
    this.overlay.hide();
    this.content.hide();
  },

  createElements: function() {
    this.builded = true;
    this.overlay = new Element('div');
    $(document.body).insert(this.overlay);
    this.overlay.setStyle({
      position: this.IE6 ? 'absolute' : 'fixed',
      width:'100%', height:'100%',
      backgroundColor:'#fff',
      top:0, left:0, zIndex:10000,
      display:'none'
    });
    this.overlay.setOpacity(0.5);

    this.content = new Element('div');
    this.content.setStyle({position: this.IE6 ? 'absolute' : 'fixed', zIndex:10001, overflow:'hidden', display:'none'});
    this.content.setOpacity(1);

    $(document.body).insert(this.overlay);
    $(document.body).insert(this.content);
  },

  fixDimensions: function() {
    var d = document.viewport.getDimensions(), c = this.content;
    s = {
      w: c.scrollWidth,
      h: c.scrollHeight
    };
    c.setStyle('width:'+s.w+'px;height:'+s.h+'px;top:50%;left:50%;margin:-'+parseInt(s.h/2)+'px 0 0 -'+parseInt(s.w/2)+'px;');

    if (this.IE6) {
      this.overlay.setStyle('width:'+d.width+'px;height:'+d.height+'px');
    }
  },

  fixScroll: function() {
    if (this.IE6) {
      s = document.viewport.getScrollOffsets();
      this.overlay.setStyle('margin-top:' + s.top + 'px;margin-left:' + s.left + 'px');
    }

    var v = document.viewport.getDimensions(),
      c = this.content,
      d = c.getDimensions(),
			t = s.top + parseInt((v.height - d.height) / 2, 10),
			l = s.left + parseInt((v.width - d.width) / 2, 10);

		c.setStyle('margin:0;top:'+t+'px;left:'+l+'px');

  }
};

function popup(url, target, width, height, features) {
    var features1 = 'width=' + width + ',height=' + height;
    if (screen) {
        features1 += ',left=' + (screen.width - width) / 2 +
                ',top=' + (screen.height - height) /2;
    }
    if (features) {
        features1 += ',' + features;
    }
    var wnd = window.open(url, target, features1);
    wnd.focus();
    return wnd;
}

function openURLInPopup(url, width, height, name) {
    if (typeof(width) == "undefined") {
        width = 800;
        height = 600;
    }
    if (typeof(height) == "undefined") {
        height = 600;
    }
    popup(url, name || 'window' + Math.floor(Math.random() * 10000 + 1), width, height, 'menubar=0,location=0,toolbar=0,status=0,scrollbars=1');
}


function set_cookie(name, value, expires, path, domain, secure) {
    document.cookie = name + "=" + escape(value) +
        ((expires) ? "; expires=" + expires.toGMTString() : "") +
        ((path) ? "; path=" + path : "") +
        ((domain) ? "; domain=" + domain : "") +
        ((secure) ? "; secure" : "");
}

function get_cookie(name) {
  var nameEQ = name + "=";
  var ca = document.cookie.split(';');
  for(var i = 0; i < ca.length; i++){
      var c = ca[i];
      while(c.charAt(0) == ' ')
      c = c.substring(1,c.length);
      if(c.indexOf(nameEQ) == 0)
      return c.substring(nameEQ.length,c.length);
  }
  return null;
}

function delete_cookie(name, path, domain) {
    if (get_cookie(name)) {
        document.cookie = name + "=" +
            ((path) ? "; path=" + path : "") +
            ((domain) ? "; domain=" + domain : "") +
            "; expires=Thu, 01-Jan-70 00:00:01 GMT";
    }
}

//~ Extending Prototype
Array.prototype.sum = function() {
  var sum = 0;
  for (var i = 0; i < this.length; i++) {
    sum += this[i];
  }
  return sum;
};



SimpleBox = Class.create({
  initialize: function(id) {
    this.id = id;
  },
  callMethod: function(method, parameters, callback) {
    callback = callback || Prototype.emptyFunction.bind(this);

    this.ajaxOnLoading();
    new Ajax.Request(Application.boxURL, {
        parameters: {jsondata: $H({_action: 'box_method', box_id: this.id, method: method, parameters: [parameters]}).toJSON()},
        onComplete : function(transport) {
          this.ajaxOnLoaded();
          var response = Application.ajaxResponseProcess(transport);
          if (! response || response.error) {
            return;
          }
          callback.call(this, response);
        }.bind(this)
      });
  },

  ajaxOnLoading: function () {
    window.simpleUIBlocker.block(
        '<div style="text-align:center; margin:10px;">' +
        '<h1 style="display:block; margin:10px;">Asteptati...</h1><img src="/img/admin/loading.gif" width="31" height="31">' +
        '</div>', 0.5);
    return;
  },

  ajaxOnLoaded: function () {
      window.simpleUIBlocker.unblock();
      return;
  }
});

ColapsabileImageGallery = Class.create({
	initialize: function(container, dummyContainer, waitingClass, toggler) {
		this.container = $(container);
		this.dummyContainer = $(dummyContainer);
		if (! this.container || ! this.dummyContainer) {
			return false;
		}
		this.waitingClass = waitingClass;
		this.toggler = $(toggler);

		this.container.observe('click', this.clickOnMainContainerEvent.bindAsEventListener(this));
    this.containerOnAllImageLoaded(this.container, this.initToggler.bind(this));
	},

  containerOnAllImageLoaded: function(container, callback) {
    var image_status = container.select('img').pluck('complete').uniq();
    if (image_status.length == 1 && image_status.shift() === true) {
      //~ if (Prototype.Browser.Opera) {
        //~ opera.postError('gata...');
      //~ } else if (Prototype.Browser.Gecko) {
        //~ console.debug('gata...');
      //~ }
      callback();
      return;
    }

    //~ if (Prototype.Browser.Opera) {
      //~ opera.postError('check');
    //~ } else if (Prototype.Browser.Gecko) {
      //~ console.debug('check');
    //~ }

    arguments.callee.delay(0.03, container, callback);
	},

	initToggler: function() {
		this.originalHeight = this.container.getHeight();

    if (this.originalHeight >= this.container.scrollHeight) {
      return;
    }

    this.toggler.show();
		this.toggler.observe('click', function(event) {
				event.stop();

				this.currentStatus = this.currentStatus === 'on' ? 'off' : 'on';
				this.toggler.src = this.toggler.src.replace(/_(on|off)/, '_' + this.currentStatus);

				var maxHeight = this.container.scrollHeight;
				new Effect.Morph(this.container, {
							style: {height: (this.currentStatus === 'on' ? maxHeight : this.originalHeight) + 'px'},
							duration: 0.3
				});
			}.bind(this));
	},

	clickOnMainContainerEvent: function(event) {
		var element = event.element();

		if(! element.hasClassName('page_nav_link')) {
			return true;
		}

    event.stop();
		var href = element.tagName == 'IMG' ? element.up().href : element.href;
		this.container.startWaiting(this.waitingClass);

		new Ajax.Request(href, {
        onComplete: function(transport) {
            var response = Application.ajaxResponseProcess(transport);
            if (! response || response.error === true) {
                    return;
            }

            this.dummyContainer.update(response.html);
						this.containerOnAllImageLoaded(this.dummyContainer, this.updateGalleryFromDummy.bind(this));
				}.bind(this)
		});
	},

	updateGalleryFromDummy: function() {
  this.dummyContainer.descendants().invoke('stopObserving');
		this.container.stopWaiting();

		var heightGallery = this.dummyContainer.getHeight();

		this.container.update(this.dummyContainer.innerHTML);
		this.dummyContainer.update();

		new Effect.Morph(this.container, {
			style: {height: heightGallery + 'px'},
			duration: 0.3
		});
	}
});


Element.addMethods({
  hoverIntent: function(element, onMouseOver, onMouseOut, options) {
    var settings = Object.extend({
		  sensitivity: 7,
		  interval:    250,
		  timeout:     100
    }, options);
    settings.onMouseOver = onMouseOver || Prototype.emptyFunction;
    settings.onMouseOut = onMouseOut  || Prototype.emptyFunction;

    // previousX, previousY = previous X and Y position of mouse, set by mouseover and polling interval
		var currentX, currentY,
		    previousX, previousY;

    function track(event) {
			currentX = event.pageX;
			currentY = event.pageY;
		}

    function comparePos(event) {
			element.hoverTimer = clearTimeout(element.hoverTimer);

			// compare mouse positions to see if they've crossed the threshold
			if (( Math.abs(previousX-currentX) + Math.abs(previousY-currentY) ) < settings.sensitivity) {
				element.stopObserving("mousemove"); // unbind expensive mousemove event
				element.isHovering = true; // set hoverIntent state to true (so mouseOut can be called)
				return settings.onMouseOver.apply(element,[event]);
			} else {
				// set previous coordinates for next time
				previousX = currentX;
				previousY = currentY;

				// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
				element.hoverTimer = arguments.callee.delay(settings.interval / 1000, event);
			}
		}

    function delayedMouseOut(event) {
      element.isHovering = false;
      element.hoverTimer = clearTimeout(element.hoverTimer);
      return settings.onMouseOut.apply(element,[event]);
    }

    function mouseover(event) {
      var p = event.fromElement || event.relatedTarget;
      while (p && p != element) { try { p = p.parentNode; } catch (e) { p = element; } }
      if (p == element) {return false;}

      // set "previous" X and Y position based on initial entry point
      previousX = event.pageX;
      previousY = event.pageY;

      if (element.hoverTimer) {
			  element.hoverTimer = clearTimeout(element.hoverTimer);
      }

      element.observe('mousemove', track); // update "current" X and Y position based on mousemove
      // start polling interval (self-calling timeout) to compare mouse coordinates over time
      if (! element.isHovering) {
        //~ element.hoverTimer = compare.delay(settings.interval, Object.extend({}, event));
        element.hoverTimer = comparePos.delay(settings.interval / 1000, Object.extend({}, event));

      }
    }

    function mouseout(event) {
      var p = event.toElement || event.relatedTarget;
      while (p && p != element) { try { p = p.parentNode; } catch (e) { p = element; } }
      if (p == element) { return false;}

      if (element.hoverTimer) {
			  element.hoverTimer = clearTimeout(element.hoverTimer);
      }

      element.stopObserving("mousemove"); // unbind expensive mousemove event

				// if hoverIntent state is true, then call the mouseOut function after the specified delay
				if (element.isHovering) {
				  element.hoverTimer = delayedMouseOut.delay(settings.timeout / 1000, Object.extend({}, event));
        }
    }

    return element.observe('mouseover', mouseover).observe('mouseout', mouseout);
  }
});


mainBoxTabs = Class.create();
Object.extend(mainBoxTabs, {
  timeouts: $H([]),
  registerTimeout: function(key, fn, time) {
    this.timeouts.set(key, setTimeout(fn, time));
  },
  unregisterTimeout: function(key) {
    clearTimeout(this.timeouts.unset(key));
  }
});

Object.extend(mainBoxTabs.prototype, {
    initialize: function(containerId, startPlaying, stopNavClickEvent, timeout) {
      this.container = $(containerId);
      this.containerId = this.container.id;

      this.prefix = containerId;

      this.currentItem = 0;
      this.items = $A([]);
      this.startPlaying = startPlaying;
      this.timeout = timeout;
      this.stopNavClickEvent = stopNavClickEvent || false;
      this.initElements();
    },

    initElements: function() {
      mainBoxTabs.unregisterTimeout(this.containerId);
      var _this = this;
      this.container.select('ul.ul-nav li').each(function(item) {
          var id = parseInt(item.id.replace(_this.prefix + '_nav_link_', ''));
          _this.items.push(id);
          //~ item.observe('mouseover', _this.navItemHover.bindAsEventListener(_this, id));
          item.hoverIntent(function() {
            mainBoxTabs.unregisterTimeout(this.containerId);
            this.activateTab(id);}.bind(_this), Prototype.emptyFunction, {interval:100});
          item.observe('click', function(event) {
            if (this.stopNavClickEvent) {
              event.stop();
            }
            mainBoxTabs.unregisterTimeout(this.containerId);
            this.activateTab(id);}.bind(_this));
      });

      this.container.select('.prev').first().observe('click', _this.showPrevious.bindAsEventListener(_this));
      this.container.select('.next').first().observe('click', _this.showNext.bindAsEventListener(_this));

      if (this.startPlaying) {
        this.play();
      } else {
        this.showNext();
      }
    },

    play: function() {
        mainBoxTabs.unregisterTimeout(this.containerId);
        var idx = this.items.indexOf(this.currentItem);
        idx++;
        if (this.items[idx] == undefined) {
            idx = 0;
        }
        var id = this.items[idx];

        this.activateTab(id);
        mainBoxTabs.registerTimeout(this.containerId, arguments.callee.bind(this), this.timeout);
    },

    showNext: function() {
        mainBoxTabs.unregisterTimeout(this.containerId);
        var idx = this.items.indexOf(this.currentItem);
        idx++;
        if (this.items[idx] == undefined) {
            idx = 0;
        }
        this.activateTab(this.items[idx]);
    },

    showPrevious: function() {
        mainBoxTabs.unregisterTimeout(this.containerId);
        var idx = this.items.indexOf(this.currentItem);
        idx--;
        if (this.items[idx] == undefined) {
            idx = this.items.length - 1;
        }
        this.activateTab(this.items[idx]);
    },

    //~ navItemHover: function(id) {
        //~ mainBoxTabs.unregisterTimeout(this.containerId);
        //~ this.timeout = setTimeout(this.activateTab.bind(this, id), 200);
    //~ },

    activateTab: function(id) {
        if (this.currentItem == id) {
            return;
        }
        this.currentItem = id;
        this.container.select('.item').invoke('hide');

        var container = this.prefix + '_container_' + id;

        $(container).show();
        $(container).select('img').first().hide().appear({ duration: 0.2 });
        this.container.select('ul.ul-nav li').invoke('removeClassName', 'on');
        $(this.prefix + '_nav_link_' + id).addClassName('on');
    }
});






