var Filip;
Filip = Filip || {};

(function($) {

  var extend = $ && $.extend || function(target, source) {
    var extended = target || {}
    ,   prop
    ;
    for (prop in source) {
      if (source.hasOwnProperty(prop) && typeof extended[prop] === 'undefined') {
        extended[prop] = source[prop];
      }
    }
    return extended;
  };


  Filip.nav = extend(Filip.nav, {
    init: function() {
      var triggerClass      = 'trigger'
      ,   triggerOpenClass  = 'open'
      ,   submenuOpenClass  = 'open'
      ,   animSpeed         = 'fast'
      ,   $sidebar          = $('#sidebar')
      ,   $nav              = $sidebar.find('.nav')
      ;

      replaceSectionLabelsWithTriggerLinks();
      initSections();
      
      function initSections() {
        $nav.find('li').each(function(i, section) {
          initSection(section);
        });
      }

      function initSection(section) {
        var $section = $(section)
        ,   $trigger = $section.find('> .' + triggerClass)
        ,   $icon    = $trigger.find('i')
        ,   $submenu = $section.find('> ul')
        ;

        function init() {
          initTrigger($trigger);
          if ($trigger.length === 0) {
            return;
          }
          updateSectionVisibility(0);
          updateIconVisibility(false, 0);
        }

        function initTrigger($trigger) {
          $trigger
            .click(handleTriggerClick)
            .hover(function() {
              updateIconVisibility(true, animSpeed);
            }, function() {
              updateIconVisibility(false, animSpeed);
            });
        }

        function isOpen() {
          return $submenu.hasClass(submenuOpenClass);
        }

        function open(animSpeed) {
          $submenu.show(animSpeed);
          ensureOpenClassesAreSet(true);
        }

        function close(animSpeed) {
          $submenu.hide(animSpeed);
          ensureOpenClassesAreSet(false);
        }

        function toggle(animSpeed) {
          ensureIsOpen(!isOpen(), animSpeed);
        }

        function updateSectionVisibility(animSpeed) {
          ensureIsOpen(isOpen(), animSpeed);
        }

        function updateIconVisibility(isTriggerHovered, animSpeed) {
          if (isTriggerHovered || isOpen()) {
            $icon.fadeIn(animSpeed);
          } else {
            $icon.fadeOut(animSpeed);
          }
        }

        function handleTriggerClick(evt) {
          toggle(animSpeed);
          evt.preventDefault();
        }

        function ensureIsOpen(openSwitch, animSpeed) {
          if (openSwitch) {
            open(animSpeed);
          } else {
            close(animSpeed);
          }
        }

        function ensureOpenClassesAreSet(shouldClassesBeSet) {
          $trigger.toggleClass(triggerOpenClass, shouldClassesBeSet);
          $submenu.toggleClass(submenuOpenClass, shouldClassesBeSet);
        }

        init();
      }

      function replaceSectionLabelsWithTriggerLinks() {
        $nav.find('span').each(function() {
          $(this).replaceWith('<a href="#" class="' + triggerClass + ' ' + this.className + '">' + $(this).text() + ' <i></i></a>');
        });
      }
    }
  });


  Filip.contactForm = Filip.contactForm || {};
  Filip.contactForm.genericMessages = extend(Filip.contactForm.genericMessages, {
      form_one_error        : 'Oj! Nie mogę wysłać formularza! Zaznaczyłem Ci pole, które nie jest dobrze wypełnione. Proszę, popraw je i spróbuj ponownie!'
    , form_multiple_errors  : 'Oj! Nie mogę wysłać formularza! Zaznaczyłem Ci {0} pola, które nie są dobrze wypełnione. Proszę, popraw je i spróbuj ponownie!'
    , form_errors_supressed : 'Dzięki -- tak lepiej! Możesz wysłać formularz, gdy tylko skończysz poprawki.'
    , required              : 'Proszę, wypełnij pole \'{0}\''
    , required_textarea     : 'Wiadomość bez treści raczej nie miałaby sensu, prawda?'
    , email                 : 'Ten adres e-mail wygląda na nieprawidłowy'
  });
  Filip.contactForm.fieldSpecificMessages = extend(Filip.contactForm.fieldSpecificMessages, {
      name: {
        required: 'Przedstaw się, nie bądź nieśmiały!'
      }    
  });
  Filip.contactForm = extend(Filip.contactForm, {
    canInit: function() {
      return jQuery.fn.validate;
    },
    init: function() {
      var autoMessages         = Filip.contactForm.genericMessages
      ,   options              = {
              messages         : Filip.contactForm.fieldSpecificMessages
            , showErrors       : handleShowErrors
            , success          : handleSuccess
            , submitHandler    : handleSubmit
            , invalidHandler   : handleInvalid
            , highlight        : highlight
      }
      ,   $form                = $('form.contact')
      ,   $submit              = $form.find('input[type=submit]')
      ,   $formMessage         = jQuery('<div class="messages"></div>').hide(0)
      ,   triedToSubmitInvalid = false
      ,   validator
      ;
      $submit.before($formMessage);
      $form.find('textarea').parent().addClass('textarea');
      validator = $form.validate(getFormValidationOptions($form, options));

      function handleInvalid(form, validator) {
        triedToSubmitInvalid = true;
        updateFormMessage();
      }

      function handleShowErrors() {
        updateFormMessage();
        this.defaultShowErrors();
      }

      function updateFormMessage() {
        var errors = validator.numberOfInvalids()
        ,   text   = ''
        ,   msgs   = Filip.contactForm.genericMessages
        ;
        if (!triedToSubmitInvalid) {
          return;
        }
        if (errors === 0 && triedToSubmitInvalid) {
          text = jQuery.validator.format(msgs.form_errors_supressed);
        } else if (errors === 1) {
          text = jQuery.validator.format(msgs.form_one_error, errors);
        } else {
          text = jQuery.validator.format(msgs.form_multiple_errors, errors);
        }
        $formMessage.show().text(text);
      }
        
      function handleSuccess(label) {
        $(label).addClass('valid-icon');
        updateFormMessage();
      }

      function handleSubmit(form) {
        form.submit();
        $submit
          .attr('disabled', 'disabled')
          .addClass('disabled')
          .val('Wysyłam...');
      }

      function highlight(element, errorClass) {
        var $element       = $(element)
        ,   numberOfBlinks = 2
        ,   blinkInterval  = 250
        ,   i              = 0
        ,   n              = numberOfBlinks * 2
        ;
        if (!lockElementForHighlighting(element)) {
          return;
        }
        $element.addClass(errorClass);
        (function blink() {
          var doneBlinking = i >= n;
          if (doneBlinking) {
            unlockElement(element);
            return;
          }
          $element.toggleClass(errorClass);
          setTimeout(blink, blinkInterval);
          i++;
        })();

        function lockElementForHighlighting(element) {
          var isAlreadyLocked;
          if (!highlight.locks) {
            highlight.locks = {};
          }
          isAlreadyLocked = highlight.locks[element.name];
          if (isAlreadyLocked) {
            return false;
          }
          highlight.locks[element.name] = true;
          return true;
        }

        function unlockElement(element) {
          highlight.locks[element.name] = false;
        }
      }

      function getFormValidationOptions($form, baseOptions) {
        var options = baseOptions || {};
        $form.find('input, textarea, select').each(function(i, field) {
          addFieldToValidationOptions(field, options);
        });
        return options;
      }

      function addFieldToValidationOptions(fieldElem, options) {
        var $field   = $(fieldElem)
        ,   name     = fieldElem.name
        ,   label    = getAssociatedLabel(fieldElem)
        ,   caption  = trim(getTextFromDirectTextNodeChildren(label))
        ,   rules
        ,   messages
        ,   captionContainsEmail
        ,   nameAttrContainsEmail
        ;
        options.rules = options.rules || {};
        options.messages = options.messages || {};
        options.rules[name] = options.rules[name] || {};
        options.messages[name] = options.messages[name] || {};
        rules = options.rules[name];
        messages = options.messages[name];

        if ($(label).text().indexOf('*') !== -1 ) {
          addRule('required', true);
          if (fieldElem.tagName === 'TEXTAREA') {
            addMessage('required', autoMessages.required_textarea, [caption]);
          } else {
            addMessage('required', autoMessages.required, [caption]);
          }
        }

        captionContainsEmail = /(^|\s)e[^\s]+mail(\s|$)/i.test(caption);
        nameAttrContainsEmail = $field.attr('name').indexOf('email') !== -1;
        if (captionContainsEmail || nameAttrContainsEmail) {
          addRule('email', true);
          addMessage('email', autoMessages.email);
        }
       
        function addRule(pluginName, value) {
          var ruleAlreadyAdded = typeof rules[pluginName] !== 'undefined';
          if (ruleAlreadyAdded) {
            return;
          }
          rules[pluginName] = value;
        }

        function addMessage(pluginName, messageFormat, messageParams) {
          var formatArgs
          ,   message
          ,   messageAlreadyAdded = (typeof messages[pluginName] !== 'undefined')
          ;
          if (messageAlreadyAdded) {
            return;
          }
          formatArgs = [messageFormat].concat(messageParams || []);
          message = jQuery.validator.format.apply(jQuery.validator, formatArgs);
          messages[pluginName] = message;
        }
      }

      function trim(str) {
        return str && str.replace(/^\s+|\s+$/g, '') || '';
      }

      function getTextFromDirectTextNodeChildren(elem) {
        var TEXT_NODE = 3
        ,   text      = ''
        ,   children
        ,   child
        ,   i
        ,   n
        ;
        if (!elem) {
          return '';
        }
        children = elem.childNodes;
        for (i = 0, n = children.length; i < n; i++) {
          child = children[i];
          if (child.nodeType === TEXT_NODE) {
            text += child.nodeValue;
          }
        }
        return text;
      }

      function getAssociatedLabel(fieldElem) {
        return $('label[for=' + fieldElem.id + ']')[0] || null;
      }
    }
  });


  Filip.gallery = extend(Filip.gallery, {
    canInit: function() {
      return !!jQuery.fn.lightBox;
    },
    init: function() {
      var imgPath = 'layout/frontend/img/lightbox/'
      ,   $imageLinks = $('ul.thumbnails > li > a')
      ;
      if ($imageLinks.length === 0) {
        return;
      } 
      $imageLinks.lightBox({
        overlayBgColor       : '#000',
        overlayOpacity       : 0.8,
        imageLoading         : imgPath + 'loading.gif',
        imageBtnClose        : imgPath + 'close.png',
        imageBtnPrev         : imgPath + 'prev.png',
        imageBtnNext         : imgPath + 'next.png',
        containerResizeSpeed : 350,
        txtImage             : 'Zdjęcie',
        txtOf                : 'z'
      });
      Filip.useFakeBody();
    }
  });


  Filip.partners = extend(Filip.partners, {
    init: function() {
      $('#main ul.partners > li').each(function(i, item) {
        var openClass    = 'open'
        ,   $item        = $(item)
        ,   $description = $item.find('> .description')
        ;
        $item.find('> h2').wrapInner('<a href="#"></a>');
        $item.find('> h2 > a').click(function(evt) {
          evt.preventDefault();
          $item.toggleClass(openClass);
          update('fast');
        });
        update(0);

        function update(animSpeed) {
          if ($item.hasClass(openClass)) {
            $description.slideDown(animSpeed);
          } else {
            $description.slideUp(animSpeed);
          }
        }
      });
    }
  });
  

  Filip = extend(Filip, {
    hoverClass: function($el, className) {
      $el.hover(function() {
        $el.addClass(className);
      }, function() {
        $el.removeClass(className);
      });
    },
    useFakeBody: function() {
      $('body').addClass('use-fake-body');
      $('#masthead, #main, #sidebar').wrapAll('<div class="fake-body"></div>');
    },
    canInit: function() {
      var isJQueryAvailable = typeof $ !== 'undefined' && typeof jQuery !== 'undefined' && jQuery === $;
      return isJQueryAvailable;
    },
    init: function() {
      Filip.nav.init();
      if (Filip.contactForm.canInit()) {
        Filip.contactForm.init();
      }
      if (Filip.gallery.canInit()) {
        Filip.gallery.init();
      }
      Filip.partners.init();
      Filip.hoverClass($('input[type=submit]'), 'hover');
    }
  });


  if (Filip.canInit()) {
    $(window).load(Filip.init);
  }

})(jQuery);

