/*
 * --------------------------------------------------------------------
 * jQuery-Plugin - accessibleUISlider - creates a UI slider component from a select element(s)
 * by Scott Jehl, scott@filamentgroup.com
 * http://www.filamentgroup.com
 * reference article: http://www.filamentgroup.com/lab/progressive_enhancement_convert_select_box_to_accessible_jquery_ui_slider
 * demo page: http://www.filamentgroup.com/examples/slider/demo.html
 * 
 * Copyright (c) 2008 Filament Group, Inc
 * Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses.
 *
 * Usage Notes: please refer to our article above for documentation
 *  
 * Version: 1.0, 08.12.08
 * Changelog: 
 * 	
 * --------------------------------------------------------------------
 */



jQuery.fn.accessibleUISlider = function(settings){
	var selects = jQuery(this);

	//id attrs - selects need ids for this feature to work - links handles to original select menus
	var elIds = (function(){
		var tempArr = [];
		selects.each(function(){
			tempArr.push(jQuery(this).attr('id'));
		});
		return tempArr;
	})();
	
	//array of all option elements in select element
	var options = (function(){
		var opts = [];
		selects.eq(0).find('option').each(function(i){
			opts.push({
				value: jQuery(this).attr('value'),
				text: jQuery(this).text()
			});
		});
		return opts;
	})();
	
	//presets by selected indexes
	var presets = (function(){
		var indexes = [];
		selects.each(function(){
	    var thisIndex = jQuery(this).find('option:selected').get(0).index;
			var thisPercentage = Math.round((thisIndex / (options.length-1)) *100);
			indexes.push(thisPercentage);
		});
		return indexes;
	})();
	
	//set up slider options API
	var sliderAPI = jQuery.extend({
		labels: 3,
		inject: true,
		rangeOpacity: 0.7,
		width: selects.parent().width(),
		range: selects.length > 1,//boolean for whether it's a range or not
		steps: options.length-1,
		stepping: 0,
		handles: function(){//set starting locations to selected index, if applicable
				var tempArr = [];
				selects.each(function(i){
					tempArr[i] = {
						start: presets[i],
						min: 0,
						max: 100,
						id: 'handle_'+i
					};
				});
				return tempArr;
			}(),
		slide: function(e, ui) {//slide function
				var that = jQuery(this);
				var currValue = ui.value;
				var currIndex = Math.round(currValue / 100 * (options.length-1));
				var currValue = options[currIndex].value;
				var currText = options[currIndex].text;
				//handle feedback tooltip and aria attrs
				var feedback = ui.handle.find('.ui-slider-tooltip'); 
				feedback.html(currText).parent().attr('aria-valuetext', currValue).attr('aria-valuenow', currValue);
				//control original select menu
				var currSelect = jQuery('#'+ui.handle.attr('id').split('handle_')[1]);
				currSelect.find('option').eq(currIndex).attr('selected', 'selected');
			}
	}, settings);
		
	selects.change(function(){
		var thisIndex = jQuery(this).find('option:selected').get(0).index;
		var thisLeft = Math.ceil((thisIndex / (options.length-1))* 100);
		var thisIndex = jQuery('#handle_'+ jQuery(this).attr('id')).parent().prev('a').size();
		jQuery('#handle_'+ jQuery(this).attr('id')).parents('.ui-slider:eq(0)').slider("moveTo", thisLeft,thisIndex);
	});
	
	//opt groups if present
	var groups = (function(){
		if(selects.eq(0).find('optgroup').size()>0){
			var groupedData = [];
			selects.eq(0).find('optgroup').each(function(i){
				groupedData[i] = {};
				groupedData[i].label = jQuery(this).attr('label');
				groupedData[i].options = [];
				jQuery(this).find('option').each(function(){
					groupedData[i].options.push({text: jQuery(this).text(), value: jQuery(this).attr('value')});
				});
			});
			return groupedData;
		}
		else return false;
	})();	

	//create slider component div
	var sliderComponent = jQuery('<div class="sliderComponent"></div>');
	
	//CREATE HANDLES
	selects.each(function(i){
		sliderComponent.append('<div id="handle_'+elIds[i]+'" tabindex="'+ i+1 +'" class="ui-slider-handle ui-default-state" role="slider" aria-valuemin="'+ sliderAPI.minValue +'" aria-valuemax="'+  sliderAPI.maxValue +'"><span class="ui-slider-tooltip ui-component-content"></span></div>');
	});
	
	//CREATE SCALE AND TICS
	sliderComponent.width(sliderAPI.width);
	
	//write dl if there are optgroups
	if(groups) {
		var scale = sliderComponent.append('<dl class="ui-slider-scale"></dl>').find('.ui-slider-scale:eq(0)');
		jQuery(groups).each(function(){
			scale.append('<dt><span>'+this.label+'</span></dt>');//class name becomes camelCased label
			var groupOpts = this.options;
			jQuery(this.options).each(function(i){
				scale.append('<dd><span class="ui-slider-label">'+ groupOpts[i].text +'</span><span class="ui-slider-tic ui-component-content"></span></dd>');
			});
		});
	}
	//write ol
	else {
		var scale = sliderComponent.append('<ol class="ui-slider-scale"></ol>').find('.ui-slider-scale:eq(0)');
		jQuery(options).each(function(){
			scale.append('<li><span class="ui-slider-label">'+this.text+'</span><span class="ui-slider-tic ui-component-content"></span></li>');
		});
	}
	
	//style the li's or dd's
	sliderComponent.find('.ui-slider-scale li, .ui-slider-scale dd').each(function(i){
		jQuery(this).css({
			'left': ((100 /( options.length-1))*i).toFixed(2) + '%'
		});
	});
	
	//first and last classes, and right align the last li/dd
	sliderComponent.find('.ui-slider-scale li:first, .ui-slider-scale dd:first').addClass('first');
	sliderComponent.find('.ui-slider-scale li:last, .ui-slider-scale dd:last').addClass('last').each(function(){ 
		jQuery(this).css({'right': 0, 'left':'auto'});
	});
	
	//show and hide labels depending on showLabels pref
	//show the last one if there are more than 1 specified
	if(sliderAPI.labels > 1) sliderComponent.find('.ui-slider-scale li:last span.ui-slider-label, .ui-slider-scale dd:last span.ui-slider-label').css('text-indent', 0).addClass('ui-slider-label-show');
	//set increment
	var increm = Math.round(options.length / sliderAPI.labels);
	//show em based on inc
	for(var j=0; j<options.length; j+=increm){
		if((options.length - j) > increm){//don't show if it's too close to the end label
			sliderComponent.find('.ui-slider-scale li:eq('+ j +') span.ui-slider-label, .ui-slider-scale dd:eq('+ j +') span.ui-slider-label').addClass('ui-slider-label-show');
		}
	}

	//style the dt's
	sliderComponent.find('.ui-slider-scale dt').each(function(i){
		var aPixel = ((3 / sliderAPI.width) * 100).toFixed(2);
		jQuery(this).css({
			'left': ((100 /( groups.length))*i).toFixed(2) + '%',
			'width': (((sliderAPI.width / groups.length) / sliderAPI.width) * 100).toFixed(2)- aPixel +'%'
		});
	});
	
	sliderAPI.markup = sliderComponent;
	
	//port slider function to pass api in.
	sliderAPI.markup.slider = function(settings){
		var sliderAPI_port = jQuery.extend(sliderAPI, settings);		
		jQuery(this).slider(sliderAPI_port).find('.ui-slider-range').css('opacity', sliderAPI_port.rangeOpacity);
		return this;
	}
	
	//if inject is true, inject slider after last select element and init, otherwise return api including markup
	if(sliderAPI.inject){
		sliderAPI.markup.insertAfter(jQuery(this).eq(this.length-1)).slider(sliderAPI).find('.ui-slider-range').css('opacity', sliderAPI.rangeOpacity);
		return this;
	}
	else{
		return sliderAPI;
	}

}




SK.dateSliderSubmit = false;

SK.drawEvents = function(daysInRange, events){
  var canvas = $('#canvas')[0];
  if (typeof G_vmlCanvasManager != 'undefined') {
    var canvasElement = document.createElement('canvas');
    var existingCanvasElement = $('#canvas')[0];
    
    $(canvasElement).attr("width", $(existingCanvasElement).attr("width"))
    $(canvasElement).attr("height", $(existingCanvasElement).attr("height"))    
    $(canvasElement).css("position", $(existingCanvasElement).css("position"))
    
    $(existingCanvasElement).remove();
    $(canvasElement).attr("id", "canvas")    
    $('.ui-slider-range').append($(canvasElement));
    
    G_vmlCanvasManager.initElement(canvasElement);
    var ctx = canvasElement.getContext('2d');
    canvas = G_vmlCanvasManager.initElement(canvasElement);
  }
  if (canvas.getContext) {
    handleWidth = $('#handle_start_date').width();
    canvasWidth = $('#canvas').width() - handleWidth;
    SK.offsetCanvas();
    dayWidth = 1;
    if (daysInRange < canvasWidth) {
      dayWidth = Math.ceil(canvasWidth / daysInRange);
    }
    $.each(events, function(i,event){
      eventStartDate = event[0];
      eventDuration = event[1];
      eventOffset = eventStartDate/daysInRange * (canvasWidth - dayWidth);
      if(daysInRange < canvasWidth) eventOffset = Math.ceil(eventOffset) //slightly less accurate over large ranges, but more pretty
      var ctx = canvas.getContext("2d");
      ctx.fillStyle = "rgb(80,80,80)";
      ctx.fillRect (eventOffset + handleWidth/2, 0, dayWidth*eventDuration, 100);
    });
  }
}

SK.offsetCanvas = function() {
  $('#canvas').css('left','-'+ $('.ui-slider-range').css('left'));
}

SK.dateSlider = {
  datesForm: '#date-selector',
  startDate: 'select#start_date',
  endDate: 'select#end_date',
  options: {
    // DO NOT USE inject: false - it's buggy and creates a duplicate ui-slider-range element
    labels: false,
    rangeOpacity: 0.5
  },
  dateSlider: false,

  createDateSliderObject: function(){
    $('select#start_date, select#end_date').accessibleUISlider(this.options);
    this.dateSlider = $(this.endDate).next(); //this is nasty but the plugin gives no ID or easy way to access this reliably
  },

  injectDateSliderObject: function(){
    this.dateSlider.appendTo(this.datesForm);
    // forces text into tooltips
    $(this.startDate).trigger('change');
    $(this.endDate).trigger('change');

    // Set action for slider change
    this.dateSlider
      .bind('slidechange', function(){
        $(SK.dateSlider.datesForm).submit();
      })
      .bind('slide', function(){
        SK.offsetCanvas();
      })
    sliderWidth = $('.sliderComponent').width()
    $('.ui-slider-range').append("<canvas id='canvas' width='"+sliderWidth+"' height='28' style='position:absolute;top:0;'>");
  },

  duplicateFirstStartDate: function(){
    var firstStartDate = $(this.startDate).find('option:first');

    // If endDate does not yet have the firstStartDate's optiongroup
    if ($(this.endDate).children('optgroup[label='+$(firstStartDate).parent().attr("label")+']').length == 0) {
      // Take a copy
      copiedOptGroup = $(firstStartDate).parent().clone();
      $(copiedOptGroup.find('option:selected')).removeAttr("selected");
      $(this.endDate).prepend(copiedOptGroup);
    } else {
      // Copy the option over, but not its selected state
      copiedOption = $(firstStartDate).clone();
      if (jQuery.browser.safari) {
        copiedOption[0].selected = false;
      } else {
        copiedOption.removeAttr("selected");
      }
      $(this.endDate).children('optgroup:first').prepend(copiedOption);
    }
  },

  duplicateLastEndDate: function(){
    var lastEndDate = $(this.endDate).find('option:last');

    // If startDate does not yet have the lastEndDate's optiongroup
    if ($(this.startDate).children('optgroup[label='+$(lastEndDate).parent().attr("label")+']').length == 0) {
      // Take a copy
      copiedOptGroup = $(lastEndDate).parent().clone();
      $(copiedOptGroup.find('option:selected')).removeAttr("selected");
      $(this.startDate).append(copiedOptGroup);
    } else {
      // Copy the option over, but not its selected state
      copiedOption = $(lastEndDate).clone();
      if (jQuery.browser.safari) {
        copiedOption[0].selected = false;
      } else {
        copiedOption.removeAttr("selected");
      }
      $(this.startDate).children('optgroup:last').append(copiedOption);
    }
  },

  init: function() {
    this.duplicateFirstStartDate();
    this.duplicateLastEndDate();
    this.createDateSliderObject();

    // Hide replaced form elements
    $(this.datesForm)
      .addClass('persistent')
      .children().hide();

    this.injectDateSliderObject();

    $(this.datesForm).submit(function(){
      // Ignore Opera - it doesn't redraw the page properly
      if (!$.browser.opera) {
        $(this).ajaxSubmit({
          data: {
            'format': 'js'
          },
      	  target: "#listings_area",
          beforeSend: function(XMLHttpRequest) {
                    if(SK.dateSliderSubmit) {
                      SK.dateSliderSubmit.abort();
                    }
            SK.dateSliderSubmit = XMLHttpRequest;
          },
      	  beforeSubmit: SK.ajaxFeedback.prepareForm
      	});
        return false;
      }
    });
  }
}

// review this
SK.Gigographies = {
  seeDates: function() {
    var group = $(this).parents('li')
    var link = $(this);
    var label = link.children('.toggle-label');

    if (!link.hasClass('open')) {

      link.addClass('open')
      
      if (group.children('.gigography').length > 0) {
        group.children('.gigography').slideToggle();
        label.text("Close");        
        
      } else {

        loader = $(document.createElement("div"))
          .addClass("ajax-pending-gigography")
          .appendTo(group)
        
        $(document.createElement("ol"))
          .addClass("gigography")
          .load(link.attr('href').replace("format=html", "format=js")+"&format=js",
            '',
            function() {
              label.text("Close");
              $(this).replaceAll(loader)
            }
          )
      }

    } else {// gigography details are displaying - hide them
      
      link.removeClass('open')
      group.children('.gigography').slideToggle();
      label.text("See events");

    }
    return false;
  },

  bindEvents: function() {
    $('h2 a.toggle-events').livequery('click', SK.Gigographies.seeDates);
  },

  init: function() {
    SK.Gigographies.bindEvents();
  }
}
