// JQuery Zimetrix Audience Popup Plugin
(function($) {

  if( typeof $ != "undefined" ) {
    var undefined = void 0;

    $.fn.zAudiencePopup = function( options ) {

      // Если селектор пуст - возвращаемся
      if( !this.length ) {
        return this;
      }

      // -- Настройки по-умолчанию --
      var settings = {
        mainClass: 'ui-zAudiencePopup',
        mainSideClass: 'ui-zAudiencePopup-right',
        otherSideClass: 'ui-zAudiencePopup-left',
        extraClass: null,
        popupTitle: null,
        /* Может быть строкой либо функцией, возвращающей
           строку, dom-элемент или объек jQuery */
        content: null,
        dataAttr: 'z:audience',
        commonUrl: null,
        offsetX: 10,
        offsetY: -10,
        hideSpeed: 'fast',
        hideTimeout: 100,
        closeAfterClickOn: null
      };
      $.extend( settings, options );

      // Установка событий
      var events = ['onBeforeShow'];
      for( var i = 0; i < events.length; i++ ) {
        var event = events[i];
        if( settings[event] && !$.isFunction(settings[event]) ) {
          delete settings[event];
        }
      }

      // -- Приватные свойства --
      var $popup = $('<div class="' + (settings.extraClass !== null ? [settings.extraClass, settings.mainClass].join(' ') : settings.mainClass) + '">\
                        <div class="content">\
                          <h3></h3>\
                          <div>\
                          </div>\
                          <div class="bottom">\
                            <div class="corn"></div>\
                          </div>\
                        </div>\
                        <div class="corner"></div>\
                      </div>');

      $popup.css({
        position: 'absolute'
      }).hover( function() {
          preventPopupHiding();
          immidiateShowPopup();
        }, function() {
          hidePopup();
      });

      // Привязывем переход по заданному url при клике на popup-е
      /*if (settings.clickUrl.constructor == String) {
        $popup.css({
          cursor: 'pointer'
        }).click( function(e) {
          window.location = settings.clickUrl;
          return false;
        })
      }*/

      var $popupTitle = $popup.find('h3:first');
      var $popupContent = $popup.find('div.content > div:first');
      var timeoutId = 0;

      // -- Публичные свойства --

      // -- Приватные методы --
      function parseParameters( paramsStr ) {
        var paramsJSON = eval( '(' + paramsStr + ')' ) || [] ;
        if( !$.isArray(paramsJSON) ) {
          paramsJSON = [paramsJSON];
        }
        // Костыль (удаляем последний элемент, если он false)
        if (paramsJSON[paramsJSON.length-1] === false) {
          paramsJSON.pop();
        }
        return paramsJSON;
      }

      function preventPopupHiding() {
        if( timeoutId != 0 ) {
          clearTimeout( timeoutId );
          timeoutId = 0;
        }
      }

      function hidePopup() {
        timeoutId = setTimeout( function() {
          hideBlock();
          timeoutId = 0;
        }, settings.hideTimeout);
      }

      // Поведение показывания/скрытия попапа в зависимости от браузера
      if ($.browser.msie) {
        var hideBlock = function() {
          $popup.hide();
        };
        var showBlock = function() {
          $popup.show();
        };
      } else {
        hideBlock = function() {
          $popup.fadeOut(settings.hideSpeed);
        };
        showBlock = function() {
          $popup.fadeIn(settings.hideSpeed);
        };
      }
      var immidiateShowPopup = function() {
        $popup.stop().show().css("opacity", 1);
      };

      // Скрытие попапа при щелчке на нем (если надо)
      if( settings.closeAfterClickOn ) {
        if( settings.closeAfterClickOn === true ) {
          // Закрываем окно при клике на любом элементе, содержащемся в $popupContent
          $popupContent.click( function(e) {
            if( e.target !== this ) {
              $popup.hide();
            }
          })
        } else {
          // Предполагаем, что получен селектор, объект или массив объектов, при клике не которых должно скрываться окно
          $popupContent.click( function(e) {
            var $elemsToCloseOn = $popupContent.find(settings.closeAfterClickOn);
            if( $.inArray(e.target, $elemsToCloseOn.get())!=-1 ) {
              $popup.hide();
            }
          })
        }
      }

      // -- Проходим через все переданные объекты
      var $elems = ( settings.content === null ) ? this.filter('*[' + settings.dataAttr + ']') : this;

      if( $elems.length ) {
        $popup.hide().appendTo( document.body );
      }

      $elems.each( function() {
        var $elem = $(this);

        // Определяем поведение попап-а
        if( settings.content !== null ) {
          var content = settings.content; 
        } else {

          var paramsJSON = parseParameters( $elem.attr(settings.dataAttr) );
          // Выставляем переход по ссылке при щелчке на элементе
          var mainHref = null;
          if( paramsJSON.length && paramsJSON[0].href ) {
            mainHref = paramsJSON[0].href;
          } else if( settings.commonUrl ) {
            mainHref = settings.commonUrl;
          }

          if( mainHref != null ) {
            $elem.click( function() {
              window.location.href = mainHref;
            });
          }

          // Если указаны элементы, которые нужно поднимать, скрываем их
          if( paramsJSON.length && paramsJSON[0].popupElems ) {
            var $popupElems = $( paramsJSON[0].popupElems ).hide();
          }
        }

        // Вывод попапа при наведении на элементе
        $elem.hover( function() {
          // Не поднимаем попам, если у него уже нет нужного атрибута
          if( !$elem.attr(settings.dataAttr) && settings.content == null ) {
            return true;
          }
          settings.popupTitle === null ? $popupTitle.hide() : $popupTitle.text( $elem.attr('title') || settings.popupTitle );
          // Чистим $popupContent ($.empty убивает все события, поэтому его не используем)
          var child;
          while( child = $popupContent[0].firstChild ) {
            $popupContent[0].removeChild( child );
          }

          if( content ) {
            // Если нужно поднимать контент пользователя
            if( $.isFunction(content) ) {
              var result = content( $elem, $popupContent, $popup );
              if( result === false ) {
                return false;
              } else {
                $popupContent.html( result );
              }
            } else {
              $popupContent.html( content );
            }
          } else if( $popupElems ) {
            // Если указано, что нужно поднимать div
            $popupElems.appendTo($popupContent).show();
          } else {
            // Если нужно генерировать контент из параметра
            var popupList = document.createElement('ul');
            for( var i = 0; i < paramsJSON.length; i++ ) {
              var link = null;
              if( !paramsJSON[i].noUrl ) {
                link = paramsJSON[i].href || settings.commonUrl;
              }
              var itemClass = paramsJSON[i].hasOwnProperty('cssClass') ? paramsJSON[i].cssClass : undefined;
              var item = $('<li>');
              if( itemClass !== undefined ) {
                item.addClass( itemClass );
              }
              if( 'count' in paramsJSON[i] ) {
                var innerItem = link ? $('<a>').attr( 'href', link ) : $('<span>');
                innerItem.text( paramsJSON[i].count );
                item.append( [ innerItem[0], document.createTextNode(': ' + paramsJSON[i].title) ] );
              } else {
                innerItem = link ? $('<a>').attr( 'href', link ).text( paramsJSON[i].title ) : document.createTextNode( paramsJSON[i].title );
                item.append( innerItem );
              }
              if( paramsJSON[i].hasOwnProperty('userAttrs') ) {
                var attrs = paramsJSON[i].userAttrs;
                for( var attr in attrs ) {
                  if( attr.toLowerCase().indexOf('on') == 0 ) {
                    innerItem[0][attr] = new Function(attrs[attr]);
                  } else {
                    innerItem.attr( attr, attrs[attr] );
                  }
                }
              }
              item.appendTo( popupList );
            }
            $popupContent.append( popupList );
          }

          if( !$popup.is(':hidden') ){
            immidiateShowPopup();
          }
          preventPopupHiding();
          showBlock();

          $popup.css({
            top : $elem.offset().top + $elem.height()/2 + settings.offsetY,
            left: -1000 // Костыль
          });
          if( $elem.offset().left + settings.offsetX + $elem.width() + $popup.width() > $(window).width() ){
            $popup.css({
              left: $elem.offset().left - $popup.outerWidth() - settings.offsetX
            }).removeClass( settings.mainSideClass ).addClass( settings.otherSideClass );
          } else {
            $popup.css({
              left: $elem.offset().left + $elem.width() + settings.offsetX
            }).removeClass( settings.otherSideClass ).addClass( settings.mainSideClass );
          }
        }, hidePopup );
      });

      // Возвращаем исходный jQuery-объект, чтобы не прерывать цепь
      return this;
    }
  } else {
    var errorMsg = "jquery.zAudiencePopup.js:\nThis is jQuery plugin, so jQuery is needed!";
    if( typeof console != "undefined" && console.error != "function" ) {
//      console.error( errorMsg );
    } else {
      alert( errorMsg );
    }
  }
})(jQuery);