/*
 * Guildhall School of Music & Drama
 * http://gsmd.ac.uk/
 *
 * Copyright 2010, Guildhall School of Musica & Drama
 * Authors: Alt N Solutions, Intro Partnership LLP
 */

if (!window.console) window.console = { log: function (msg) {} };

var gsmd = {};

gsmd.getStyle = function (element, property) {
  if (element.currentStyle) {
    return element.currentStyle[property];
  } else if (window.getComputedStyle) {
    return window.getComputedStyle(element, null).getPropertyValue(property);
  }
}

gsmd.middleware = {};
gsmd.middleware.Browser = $.Class.create({
  
  initialize: function (app) {
    this._app = app;
  },
  
  send: function (event) {
    return true;
  }
  
});
gsmd.middleware.GridToggle = $.Class.create({
  
  initialize: function (app) {
    this._app = app;
  },
  
  send: function (event) {
    if (event.shiftKey && event.keyCode === 7) $('.grid').toggle();
    if (event.shiftKey && event.keyCode === 18) $('.template').toggle();
    return this._app.send(event);
  }
  
});
gsmd.middleware.TourBox = $.Class.create({
  
  initialize: function (app) {
    this._app = app;
  },
  
  send: function (event) {
    switch (event.type) {
    case 'click':
      var a = event.target;
      if (a.nodeName !== 'A') a = $(event.target).parent('a')[0];
    
      if (a && a.href && a.href.indexOf('#tour') !== -1) {
        event.preventDefault();
        event.stopPropagation();
      
        switch (a.href.split('#')[1]) {
        case 'tour_open':
          gsmd.env.views.tourBox.open(); break;
        case 'tour_close':
          gsmd.env.views.tourBox.close(); break;
        }
      
        return false;
      } else return this._app.send(event);
      break;
    case 'keyup':
      if (event.keyCode == 27) {
        if (gsmd.env.views.tourBox.isOpen()) {
          event.preventDefault();
          event.stopPropagation();
          gsmd.env.views.tourBox.close();
          return false;
        }
        return this._app.send(event);
      }
      break;
    default:
      return this._app.send(event);
    }
  }
  
});

gsmd.controllers = {};
gsmd.views = {};
gsmd.helpers = {
  getStyle: function (element, property) {
    if (element.currentStyle) {
      return element.currentStyle[property];
    } else if (window.getComputedStyle) {
      return window.getComputedStyle(element, null).getPropertyValue(property);
    }
  }
};

gsmd.controllers.MainViewController = $.Class.create({
  
  initialize: function () {
    this.view().wrapBodyBullets();
    this.view().autoColumnate();
    this.view().align();
  },
  
  view: function () {
    return this._view = this._view || new gsmd.views.Main();
  }
  
});
gsmd.views.Main = $.Class.create({
  
  align: function () {
    this._alignToOtherBoxes();
  },
  
  _alignToOtherBoxes: function () {
    // TODO: smart alignment
  },
  
  wrapBodyBullets: function () {
    $('p + ul, p + ol').addClass('theme_color_hook');
    $('p + ul li, p + ol li').wrapInner('<span class="body_black"> </span>');
  },
  
  autoColumnate: function () {
    try {
      $('.auto_column').each(function() {
        var column_1 = $(this);
        column_1.addClass('box').addClass('column_box');
        var column_2 = $(column_1[0].cloneNode(false));
        column_1.before(column_2);
        
        column_1.children().each(function() {
          $(this).detach().appendTo(column_2);
          return column_2.height() < column_1.height();
        });
      });
    } catch (e) {
      console.log(e);
    }
  }
  
});

gsmd.controllers.CarouselViewController = $.Class.create({
  
  initialize: function () {
    if (this.carouselDoesNotExist()) return false;
    
    this._frameView = new gsmd.views.CarouselFrameView(this.element());
    this._frameView.delegate = this;
    
    this._thumbnailView = new gsmd.views.CarouselThumbnailView(this.element());
    this._thumbnailView.delegate = this;

    this._captionView = new gsmd.views.CarouselCaptionView(this.element());
    this._captionView.delegate = this;
    
    this.prepareForAppearance();
    
    this._paused = true;
    this._locked = false;
    
    $(window).blur($.proxy(this.pause, this));
    $(window).focus($.proxy(this.resume, this));
    $(window).scroll($.proxy(this.onScroll, this));
    
    if (this._frameView.allImagesLoaded()) this.onAllImagesLoaded();
  },
  
  carouselDoesExist: function () {
    return this.element().length > 0;
  },
  carouselDoesNotExist: function () {
    return !this.carouselDoesExist();
  },
  
  element: function () {
    return this._element = this._element || $('#carousel');
  },
  
  prepareForAppearance: function () {
    this._captionView.setCaption(this._thumbnailView.getCaption());
  },
  
  onAllImagesLoaded: function () {
    this.resume();
  },
  
  onThumbnailClick: function (identifier) {
    if (this._nextTimeout != null) window.clearTimeout(this._nextTimeout);
    this._thumbnailView.select(identifier);
  },
  
  onThumbnailSelected: function (identifier) {
    this._captionView.setCaption(this._thumbnailView.getCaption());
    this._frameView.showImage(identifier);
  },
  
  onQueueCompleted: function () {
    if (this._paused) return;
    this._nextTimeout = window.setTimeout($.proxy(this.showNext, this), gsmd.settings.carousel.delay * 1000);
  },
  
  showNext: function () {
    this.onThumbnailClick('#next');
  },
  
  pause: function (lock) {
    if (this._paused) return;
    this._paused = true;
    this._locked = lock;
    if (this._nextTimeout) window.clearTimeout(this._nextTimeout);
  },
  
  resume: function (unlock) {
    if (!this._paused) return;
    if (this._locked && !unlock) return;
    this._paused = false;
    this._locked = false;
    this.onQueueCompleted();
  },
  
  onScroll: function (event) {
    this._bottom = this._bottom || (this.element().offset().top + this.element().height());
    if (this._bottom > $(window).scrollTop()) this.resume();
    else this.pause();
  },
  
  captionViewWasClicked: function (event) {
    this.gotoSelected();
  },
  frameViewWasClicked: function (event) {
    this.gotoSelected();
  },
  
  gotoSelected: function () {
    window.location = this._thumbnailView.getLinkUrl();
  }
  
});
gsmd.views.CarouselFrameView = $.Class.create({
  
  initialize: function (parent) {
    this._queue = [];
    this.parent = parent;
    this.images().load($.proxy(this.onImageLoad, this));
    this.element().click($.proxy(this.onClick, this));
  },
  
  element: function () {
    return this.parent.children('.frame').first();
  },
  
  images: function () {
    return this._images = this._images || this.element().children('img');
  },
  
  onImageLoad: function (event) {
    this.delegate && this.delegate.onImageLoad && this.delegate.onImageLoad();
    window.setTimeout($.proxy(function () {
      if (this.allImagesLoaded()) this.onAllImagesLoaded();
    }, this), 0);
  },
  
  onAllImagesLoaded: function () {
    this.delegate && this.delegate.onAllImagesLoaded && this.delegate.onAllImagesLoaded();
  },
  
  allImagesLoaded: function () {
    for (var n = 0; n < this.images().length; n++) {
      if (this.images()[n].complete !== true) return false;
    }
    
    return true;
  },
  
  showFirstImage: function () {
    this.showImage(0);
  },
  
  showImage: function (identifier) {
    this._queue.push(identifier);
    this.nextInQueue();
  },
  
  _showImage: function (identifier) {
    if (identifier === '#next') {
      var image = this._currentImage.next() || this.images().first();
    } else if (identifier === '#previous') {
      var image = this._currentImage.prev() || this.images().last();
    } else if (typeof identifier === 'number') {
      var image = $(this.images()[identifier]);
    } else if (typeof identifier == 'string') {
      var image = $(identifier);
    }
    
    if (this._currentImage && this._currentImage[0].id === image[0].id) return;
    
    this._busy = true;
    
    this.images().css('z-index', 0);
    
    if (this._currentImage) this._currentImage.css('z-index', this.images().length);
    
    this._currentImage = image;
    
    this._currentImage.css({ 'z-index': this.images().length + 1, 'opacity': 0 });
    this._currentImage.animate({ opacity: '1' }, $.proxy(this.onFadedIn, this));
  },
  
  onFadedIn: function () {
    this._busy = false;
    this.nextInQueue();
  },
  
  nextInQueue: function () {
    if (this._busy) return;
    var identifier = this._queue.shift();
    if (identifier == null) {
      this.delegate && this.delegate.onQueueCompleted && this.delegate.onQueueCompleted();
    } else {
      this._showImage(identifier);
    }
  },
  
  onClick: function (event) {
    this.delegate && this.delegate.frameViewWasClicked && this.delegate.frameViewWasClicked(event);
  }
  
});
gsmd.views.CarouselThumbnailView = $.Class.create({
  
  initialize: function (parent) {
    this.parent = parent;
    $('.menu a', this.parent).click($.proxy(this._onClick, this));
  },
  
  _onClick: function (event) {
    event.preventDefault();
    event.stopPropagation();
    var identifier = event.currentTarget.rel;
    this.delegate && this.delegate.onThumbnailClick && this.delegate.onThumbnailClick(identifier);
    return false;
  },
  
  select: function (identifier) {
    switch (identifier) {
    case '#previous':
      var prev = $('a.selected', this.parent).parent().prev()[0];
      identifier = (prev && $('a', prev)[0].rel) || $('.thumbnails a', this.parent).last()[0].rel;
      break;
    case '#next':
      var next = $('a.selected', this.parent).parent().next()[0];
      identifier = (next && $('a', next)[0].rel) || $('.thumbnails a', this.parent).first()[0].rel;
      break;
    }
    
    $('a', this.parent).removeClass('selected');
    var selected = $('a[rel="' + identifier + '"]', this.parent);
    selected.addClass('selected');
    this.delegate && this.delegate.onThumbnailSelected && this.delegate.onThumbnailSelected(identifier);
    
    var newLeft = 0;
    newLeft = selected.parent().position().left - ($('.thumbnail_mask').width() / 2) + (selected.parent().width() / 2) - 5;
    
    var last = $('li:last-child', this.parent);
    
    var maxLeft = last.position().left
                + last.width()
                - $('.thumbnail_mask', this.parent).width()
                - 5;
    
    newLeft = Math.max(0, Math.min(newLeft, maxLeft));
    
    $('.thumbnails', this.parent).animate({ left: -newLeft + 'px' });
  },
  
  getCaption: function () {
    return $('a.selected', this.parent)[0].title;
  },
  
  getLinkUrl: function () {
    return $('a.selected', this.parent)[0].href;
  }
  
});
gsmd.views.CarouselCaptionView = $.Class.create({
  
  initialize: function (parent) {
    this.parent = parent;
    this.element().click($.proxy(this.onClick, this));
  },
  
  element: function () {
    return this._element = this._element || $('.caption', this.parent);
  },
  
  setCaption: function (value) {
    this.element().html(value);
    Cufon.replace(this.element()[0]);
  },
  
  onClick: function (event) {
    this.delegate && this.delegate.captionViewWasClicked && this.delegate.captionViewWasClicked(event);
  }
  
});

gsmd.controllers.QuotesViewController = $.Class.create({
  
  initialize: function () {
    if (this.view().doesNotExist()) return;
    var quoteCount = this.view().getQuoteCount();
    var quoteToShow = this.getLastQuote() + 1;
    quoteToShow = (quoteCount + (quoteToShow % quoteCount)) % quoteCount;
    this.setLastQuote(quoteToShow);
    this.view().showQuote(quoteToShow);
  },
  
  view: function () {
    return this._view = this._view || new gsmd.views.QuotesView();
  },
  
  setLastQuote: function (value) {
    document.cookie = this.cookieKey() + '=' + value.toString();
  },
  getLastQuote: function () {
    var match = document.cookie.match(new RegExp(this.cookieKey() + '=([^;]+)'))
    if (match) return parseInt(match[1], 10);
          else return -1;
  },
  
  cookieKey: function () {
    if (!this._cookieKey) {
      this._cookieKey = '_gsmd_';
      this._cookieKey += this.view().signature();
      this._cookieKey += '_last_quote';
    }
    return this._cookieKey;
  }
  
});
gsmd.views.QuotesView = $.Class.create({
  
  element: function () {
    return this._element = this._element || $('#pullquote');
  },
  
  doesExist: function () {
    return this.element().length > 0;
  },
  doesNotExist: function () {
    return !this.doesExist();
  },
  
  quotes: function () {
    return $('.caption', this.element());
  },
  
  getQuoteCount: function () {
    return this.quotes().length;
  },
  
  showQuote: function (i) {
    this.quotes().hide();
    $(this.quotes().get(i)).show();
    this.element().css('height', 'auto');
    this.element().css('height', this.element().innerHeight());
  },
  
  signature: function () {
    return this.element().attr('name');
  }
  
});

gsmd.views.TourBoxView = $.Class.create({
  
  initialize: function () {
    
  },
  
  overlay: function () {
    if (!this._overlay) {
      this._overlay = document.createElement('div');
      this._overlay.className = 'tour_overlay';
      this._overlay.id = 'tour_overlay';
      document.body.appendChild(this._overlay);
      $(this._overlay).hide();
    }
    return this._overlay;
  },
  
  element: function () {
    if (!this._element) {
      this._element = document.createElement('div');
      this._element.className = 'tour_box';
      this._element.id = 'tour_box';
      this._element.appendChild(this.closeButton());
      this.overlay().appendChild(this._element);
      $(this._element).css({ top: '150%' });
    }
    return this._element;
  },
  
  closeButton: function () {
    if (!this._closeButton) {
      this._closeButton = document.createElement('a');
      this._closeButton.className = 'tour_close_button';
      this._closeButton.id = 'tour_close_button';
      this._closeButton.title = 'Close';
      this._closeButton.href = '#tour_close';
    }
    return this._closeButton;
  },
  
  iframe: function () {
    if (!this._iframe)
      this._iframe = $('<iframe src="' + gsmd.settings.tour.src + '" scrolling="no" frameborder="0" id="tour_box_iframe"></iframe>');
    
    return this._iframe;
  },
  
  isOpen: function () {
    return this._open === true;
  },
  
  open: function () {
    if (this._open) return;
    this._open = true;
    
    gsmd.env.carouselViewController.pause(true);
    
    $(this.element()).css({ top: '-50%' });
    $(this.element()).append(this.iframe());
    
    $(this.overlay()).fadeIn($.proxy(function () {
      $(this.element()).animate({ top: '50%' });
    }, this));
  },
  
  close: function () {
    if (!this._open) return;
    this._open = false;
    
    $(this.element()).animate({ top: '-50%' }, $.proxy(function () {
      this.iframe().detach();
      $(this.overlay()).fadeOut(function () {
        gsmd.env.carouselViewController.resume(true);
      });
    }, this));
  },
  
  onCloseClick: function (event) {
    event.preventDefault();
    event.stopPropagation();
    this.close();
    return false;
  }
  
});

gsmd.controllers.EmailFormController = $.Class.create({
  
  initialize: function () {
    $('a[href=#email_form_show]').live('click', $.proxy(this.show, this));
    $('a[href=#email_form_hide]').live('click', $.proxy(this.hide, this));
    $('#share_by_email_form').bind('submit', $.proxy(this.submit, this));
  },
  
  show: function (event) {
    event.preventDefault();
    event.stopPropagation();
    gsmd.env.views.emailForm.show();
  },
  
  hide: function (event) {
    event.preventDefault();
    event.stopPropagation();
    gsmd.env.views.emailForm.hide();
  },
  
  submit: function (event) {
    event.preventDefault();
    event.stopPropagation();
    gsmd.env.views.emailForm.lock();
    gsmd.env.views.emailForm.displayMessage('Sending…');
    $.ajax({
      type: gsmd.env.views.emailForm.method(),
      url: gsmd.env.views.emailForm.action(),
      data: gsmd.env.views.emailForm.serialize(),
      success: $.proxy(this.submitSuccess, this),
      error: $.proxy(this.submitError, this)
    });
  },
  
  submitSuccess: function (data, status, xhr) {
    gsmd.env.views.emailForm.displayMessage('Sent!');
    gsmd.env.views.emailForm.resetAndUnlock();
  },
  submitError: function (xhr, status, error) {
    gsmd.env.views.emailForm.displayMessage('Error');
    gsmd.env.views.emailForm.justUnlock();
  }
  
});
gsmd.views.EmailFormView = $.Class.create({
  
  show: function () {
    $('#share_by_email_form').fadeIn();
    this.focus();
  },
  hide: function () {
    $('#share_by_email_form').fadeOut();
  },
  
  focus: function () {
    $('#email_to').focus();
  },
  
  method: function () {
    $('#share_by_email_form').attr('method');
  },
  action: function () {
    $('#share_by_email_form').attr('action');
  },
  serialize: function () {
    $('#share_by_email_form').serialize();
  },
  
  lock: function () {
    $('#share_by_email_form input, #share_by_email_form textarea').attr('disabled', 'disabled');
  },
  unlock: function () {
    $('#share_by_email_form input, #share_by_email_form textarea').removeAttr('disabled');
  },
  reset: function () {
    $('#share_by_email_form')[0].reset();
    $('#share_by_email_form .submit_link').attr('value', this._originalSubmitValue);
  },
  
  displayMessage: function (message) {
    this._originalSubmitValue = this._originalSubmitValue || $('#share_by_email_form .submit_link').attr('value');
    $('#share_by_email_form .submit_link').attr('value', message);
  },
  
  resetAndUnlock: function (delay) {
    window.setTimeout($.proxy(function () {
      this.reset();
      this.unlock();
      this.focus();
    }, this), delay || 1500);
  },
  
  justUnlock: function (delay) {
    window.setTimeout($.proxy(function () {
      this.unlock();
      $('#share_by_email_form .submit_link').attr('value', this._originalSubmitValue);
    }, this), delay || 1500);
  }
  
});

gsmd.Environment = $.Class.create({
  
  initialize: function () {
    this._initStack();
    var self = this;
    this.__send__ = function (event) { self.send(event); };
    $(document).ready(function (event) { self._ready(); });
    $(window).load(function (event) { self._load(); });
  },
  
  send: function (event) {
    this.app.send(event);
  },
  
  _initStack: function () {
    for (var n = 0; n < gsmd.stack.length; n++)
      this.app = new gsmd.stack[n](this.app);
  },
  
  _ready: function () {
    $(document).bind('keypress', this.__send__);
    $(document).bind('keyup', this.__send__);
    $(document).bind('click', this.__send__);
    this._initQuotes();
    this._initDatepickers();
    this._initMagicLabels();
    this._initMainController();
    this._initCarouselController();
    this._initEmailFormController();
    this.views = {
      tourBox: new gsmd.views.TourBoxView(),
      emailForm: new gsmd.views.EmailFormView()
    };
  },
  
  _load: function () {
    this._blackPreload = new Image();
    this._blackPreload.src = '/images/colors-black-70.png';
  },
  
  _initQuotes: function () {
    this.quotesViewController = new gsmd.controllers.QuotesViewController();
  },
  
  _initMainController: function () {
    this.mainViewController = new gsmd.controllers.MainViewController();
  },
  
  _initCarouselController: function () {
    this.carouselViewController = new gsmd.controllers.CarouselViewController();
  },
  
  _initEmailFormController: function () {
    this.emailFormController = new gsmd.controllers.EmailFormController();
  },
  
  _initDatepickers: function () {
    $('.calendar').datepicker({
      prevText: 'Prev',
      nextText: 'Next',
      firstDay: 1,
      beforeShowDay: function (date) {
        var sampleDates = [5,6,7,8,9,10];
        var theDate = date.getDate();
        if ($.inArray(theDate, sampleDates) != -1) return [true, 'ui-state-active', 'Some Event'];
        else return [true, ''];
      }
    });
    $('.calendar').find('.ui-datepicker-header').addClass('theme_mid_border_hook');
  },
  
  _initMagicLabels: function () {
    $('#search_form').magicLabels();
    $('#whats_on_search_form').magicLabels();
    $('#news_search_form').magicLabels();
    $('#news_archive_search_form').magicLabels();
  }
  
});

gsmd.init = function () {
  gsmd.env = new gsmd.Environment();
};

gsmd.stack = [
  gsmd.middleware.Browser,
  gsmd.middleware.GridToggle,
  gsmd.middleware.TourBox
];

gsmd.settings = {
  alignment: {
    snap_threshold: 200,
    grid: 48
  },
  carousel: {
    delay: 4.5
  },
  tour: {
    src: 'http://www.gsmd.ac.uk/fileadmin/templates/deploy/Main.html'
  }
};

gsmd.init();

