var Innocent = {};

Innocent.Events = {
  common: {
    initialize: function () { external_link_targets(); },
    finalize:   function () {}
  },
  booking: {
    initialize: function () { initialize_time_dropdown(); },
    main:       function () { booking_form_validator(); }
  },
  info: {
    main: function () { initialize_google_map(); }
  }
}

Innocent.Util = {
  fire: function (sc, fn, args) {
    var ns = Innocent.Events;
    if (sc !== '' && ns[sc] && typeof ns[sc][fn] == 'function') {
      ns[sc][fn](args);
    }
  }, 
  load: function() {
    var id = document.body.id;
    Innocent.Util.fire('common', 'initialize');
    $.each(document.body.className.split(/\s+/), function(i, cl) {
      Innocent.Util.fire(cl, 'initialize');
      Innocent.Util.fire(cl, id);
    });
    Innocent.Util.fire('common', 'finalize');
  }
};

function external_link_targets() {
  $('a[rel=external]').each(function () {
    $(this).attr({ 'target': '_blank' });
  });
}

function booking_form_validator() {
  // Add compatibility method for browsers that do not support Array.reduce
  // https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array/Reduce#Compatibility
  if (!Array.prototype.reduce)  {  
    Array.prototype.reduce = function(fun /*, initial*/) {  
      var len = this.length >>> 0;  
      if (typeof fun != "function") throw new TypeError();  
      // no value to return if no initial value and an empty array  
      if (len == 0 && arguments.length == 1) throw new TypeError();  
      var i = 0;  
      if (arguments.length >= 2) {  
        var rv = arguments[1];  
      } else {  
        do {  
          if (i in this) {  
            var rv = this[i++];  
            break;  
          }  
          // if array contains no values, no initial value to return  
          if (++i >= len) throw new TypeError();  
        }  
        while (true);  
      }  
      for (; i < len; i++) { 
        if (i in this) rv = fun.call(undefined, rv, this[i], i, this); 
      }  
      return rv;  
    };  
  }
  
  $.validator.addMethod('total', function (value, element, params) {
    var elements = $(params[1].join(','));
    var values   = elements.map(function () { return parseInt(this.value) || 0; }).toArray();
    var total    = values.reduce(function (p, c) { return p + c; }) + (parseInt(value) || 0);
    return total <= params[0];
  }, 'Total cannot exceed {0}.');
  
  $().ready(function () {
    $('#booking-form').validate({
      rules: {
        'date': { required: true, range: [1, 7] },
        'time': { required: true, range: [1, 3] },
        'adult': { required: true, digits: true, min: 1, max: 6, total: [6, ['#booking-child']] },
        'child': { required: true, digits: true, range: [0, 6], total: [6, ['#booking-adult']] },
        'name': { required: true, rangelength: [3, 50] },
        'email': { required: true, minlength: 6, maxlength: 254, email: true }
      },
      messages: {
        'date': {
  	  required: 'You must select a date.',
  	  range: 'There was an error with the value you have selected.'
        },
        'time': {
  	  required: 'You must select a time.',
  	  range: 'There was an error with the value you have selected.'
        },
        'adult': {
  	  required: 'A quantity is required.',
  	  digits: 'A number is required.',
  	  min: 'Must have an adult.',
  	  max: 'Six tickets maximum.'
        },
        'child': {
  	  required: 'A quantity is required.',
  	  digits: 'A number is required.',
  	  range: 'Six tickets maximum.'
        },
        'name': {
          required: 'Please enter your name.',
          rangelength: 'Must be {0}&ndash;{1} characters long.'
        },
        'email': {
          required: 'E-mail needed for your e-ticket.',
          minlength: 'E-mail address too short.',
          maxlength: 'E-mail address too long.',
          email: 'Please enter a valid e-mail.'
        }
      }
    });
  });
}

function initialize_google_map() {
  var loc = new google.maps.LatLng(51.525881, -0.081507);
  var map = new google.maps.Map($('#map').get(0), {
    center: loc,
    mapTypeControl: true,
    mapTypeControlOptions: {
      mapTypeIds: [google.maps.MapTypeId.ROADMAP, google.maps.MapTypeId.SATELLITE, google.maps.MapTypeId.HYBRID],
      style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
    },
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    navigationControl: true,
    navigationControlOptions: {
      style: google.maps.NavigationControlStyle.SMALL
    },
    zoom: 15
  });
  var pin = new google.maps.Marker({
    icon: new google.maps.MarkerImage(
      '/img/layout/map_marker.png',
      new google.maps.Size(25, 30),
      new google.maps.Point(0, 0),
      new google.maps.Point(13, 30)
    ),
    map: map,
    position: loc,
    shadow: new google.maps.MarkerImage(
      '/img/layout/map_shadow.png',
      new google.maps.Size(42, 30),
      new google.maps.Point(0, 0),
      new google.maps.Point(13, 30)
    ),
    shape: {
      coord: [1, 1, 1, 25, 10, 25, 13, 30, 16, 25, 25, 25, 25, 1],
      type: 'poly'
    },
    title: 'Innocent Cafe @ The Tramshed, 6-8 Garden Walk, Shoreditch, London, EC2A 3EQ'
  });
  $('#directions').attr({ target: '_blank' });
}

function initialize_time_dropdown() {
  var t = $('#booking-time');
  $('<label>').html('The time has changed! Please check it is correct.')
    .addClass('error').attr({'id': 'date-changed-warning'})
    .css({'display': 'block', 'margin-left': 0}).hide().insertAfter($(t));
  $(t).live('focus', function () {
    $('#date-changed-warning').hide();
  });
  $('#booking-date').bind('change keyup', function () {
    var a = booking_dt_avail[$(this).val()];
    var s = $(t).val();
    $(t).empty();
    var exists = false;
    $.each(a, function (k, v) {
      $('<option>').val(k).html(v).appendTo('#booking-time');
      if (k == s) exists = true;
    });
    if (exists) {
      $(t).val(s);
    } else {
      $('#date-changed-warning').show();
    }
  });
}

$().ready(Innocent.Util.load);

