/*******
 * camps.js
 *  handles the retrieval of Jewish Camp results based on filter queries
 *  and the rendering of these results to the GMap2 object which JewishCampMap
 *  wraps.
 *
 *  JewishCampMap   => handles the map plotting
 *  CampResultsList => handles the sidelist of results
 *  FilterManager   => handles the filter capture and results calculations
 *
 ******/
 
var Accordion = Class.create({
  initialize: function(container) { 
    this.container = $(container);
    this.listItems = this.container.select('li');
    this.togglers = this.container.select('.accordion_toggle');
    this.contents = this.container.select('.accordion_content');
    this.dur = 0.2;
    this.setup();
  },
  setup: function() {
    this.togglers.each(function(el, i) {
      el.observe('click', this.slide.bindAsEventListener(this, i));

      // these divs are display:none before population
      el.show();
    }.bind(this));
  },
  slide: function(ev, i) {
    if(this.listItems[i].hasClassName('active')) { return; }
    this.hideAll();
    this.listItems[i].addClassName('active');
    Effect.SlideDown(this.contents[i], { 
      duration: this.dur,
      afterFinish: function() { 
        map.showBubble(this.togglers[i].id);
      }.bind(this)
    });
    if (ev) { ev.stop(); }
  },


  expandByNum: function(num) {
  // alert('invoked with ' + num);
    this.showOnly($(num).next('.accordion_content'));
    var offset = $(num).up().positionedOffset();
    new Effect.Move($(num).up().up(), {
    mode: 'absolute',
    y: -(offset.top),
    duration: this.dur
    });
    //this.slide(null, parseInt(num));
    $(num).up().up().childElements().each(function(el){
    	if(el == $(num).up()){
    	    $(num).up().addClassName('active');
    	}
    	else{
    		el.removeClassName('active');
    	}
    });
  },


  showOnly: function(el) {
    this.contents.invoke('hide');
    el.show();
  },
  hideAll: function() {
    this.contents.invoke('hide');
    this.listItems.invoke('removeClassName', 'active');
  }
});

var regions = {
    'can_us'   : {'lat': 47.830859, 'long':  -96.870119,  'zoom': 3 },
    'can'      : {'lat': 56.08675,  'long':  -92.475588,  'zoom': 3 },
    'cw'    : {'lat': 57.150545, 'long': -118.388672,  'zoom': 4 },
    'ce'    : {'lat': 50.994397, 'long':  -79.321289,  'zoom': 4 },
    'us'       : {'lat': 40.667306, 'long':  -94.746094,  'zoom': 3 },
    'ne'    : {'lat': 43.361931, 'long':  -74.051514,  'zoom': 5 },
    's'     : {'lat': 34.93278,  'long':  -86.931153,  'zoom': 4 },
    'mw'    : {'lat': 41.84665,  'long':  -94.833984,  'zoom': 5 },
    'w'     : {'lat': 42.173175, 'long': -116.857911,  'zoom': 4 },
    'se'    : {'lat': 37.0625,  'long':  -95.677068,  'zoom': 3 }
};

var accordion;

var CampResultsList = Class.create({

    initialize : function (){
      this.element = $('camp_map_results').down('ol');
      this.template = new Template(this.element.innerHTML.replace(/#%7B([a-zA-Z0-9_-]+)%7D/gi, "#{$1}"));
    },

    update: function (camps){
      var html = '';
      for (i=0; i < camps.length; i++) {
        html +=  this.campHTML(camps[i]);
      }

      this.element.innerHTML = html;

    
      this.element.show();
      if($('accordion')) {
        accordion = new Accordion('accordion');
      }
    },

    campJsonData : function (camp) {
      var camp_data = {
        id:      camp.pk,
        name:    camp.fields.name,
        city:    camp.fields.city,
        state:   camp.fields.state,
        sponsor: camp.fields.sponsor,
        email_address: camp.fields.email_address,
        summer_phone: camp.fields.summer_phone,
        winter_phone:   camp.fields.winter_phone,
        slug: "/camps/" + camp.fields.slug 
      };
      return camp_data;
    },

    campHTML : function (camp){
      return this.template.evaluate(this.campJsonData(camp)); 
    }

}); 

var FilterManager = Class.create({
    initialize : function (callback) {
      this.element = $('overlay_filter');
      this.relevantFilters = [];
      this.filters = {};
      this.results = [];  
      this.all_camps = all_camps;
      this.callback = callback;

      // If the cookie shows saved filters then set them here
      var unevaled_filters  = getCookie('camp_search_filters');
      if (unevaled_filters !== null) {
        var json_filters    = unevaled_filters.evalJSON();
        this.filters        = json_filters;

        // and make the UI reflect those criteria
        this.setFilterUI();
        //this.filterResults();
        r = this.filterResults();

        crl.update(r);
        map.update(r);

        //this.callback(this.results);
      }
      else{
        this.callback(this.all_camps);
      }

      // this.fetchResults();
    },

    allResults : function () {
      return this.all_camps;
    },

    setFilterElement: function(dom_id) {
      this.element = $( dom_id );
    },

    filterSettings: function() {
      this.recalculateFilters();
      return this.filters;
    },

    setFilterUI : function() {
      for(var i in this.filters){
        if($(i)){
          $(i).checked = this.filters[i];
        }
        else if(i == 'regions'){
        	this.filters['regions']=this.filters[i];
        	if(this.filters['regions'][0] == 'ne' 
        			&& this.filters['regions'][1] == 's' 
        			&& this.filters['regions'][2] == 'mw'
        			&& this.filters['regions'][3] == 'w'){
        		$('region').value = 'us';
        	}
        	else if(this.filters['regions'][0] == 'ce' 
        			&& this.filters['regions'][1] == 'cw'){
        		$('region').value = 'can';
        	}
        	else {
        		$('region').value = this.filters['regions'];
        	}
        }
      }
    },

    setRegion: function(region) {
      this.filters['regions'] = [];

      if (region == 'us') {
        this.filters['regions'].push ('ne', 's', 'mw', 'w');
      }

      else if (region == 'can') {
        this.filters['regions'].push ('ce', 'cw');
      }

      else {
        this.filters['regions'].push (region);
      }
      setCookie('camp_search_filters', Object.toJSON(this.filters));
      
      return this.filters['regions'];
    },

    recalculateFilters: function() {
      $$('#overlay_filter input').each(function(el) {
        this.valueFromInput(el);
      }.bind(this));
      setCookie('camp_search_filters', Object.toJSON(this.filters));
    },

    shouldFilterRegion: function() {
      var region = $('region').value;
      this.setRegion(region);
      map.panToRegion(region);
      if(region !== 'can_us') {
        this.relevantFilters.push(this.regionMatch);
      }
    },

    shouldFilterGender: function() {
      if($$('.gender').any(function(el) { return el.checked === false; })) {
        this.relevantFilters.push(this.genderMatch);
      }
    },

    shouldFilterSpecialNeeds: function() {
      if($('special_yes').checked === true) {
        this.relevantFilters.push(this.specialNeedsMatch);
      }
    },

    shouldFilterSpecialtyCamps: function() {
      if($$('.specialty').any(function(el) { return el.checked === true; })) {
        this.relevantFilters.push(this.specialtyCampsMatch);
      }
    },

    shouldFilterAffiliation: function() {
      if($$('.affiliation').any(function(el) { return el.checked === false; })) {
        this.relevantFilters.push(this.affiliationMatch);
      }
    },

    chooseRelevantFilters: function() {
      this.relevantFilters = [];
      this.shouldFilterAffiliation();
      this.shouldFilterRegion();
      this.shouldFilterGender();
      this.shouldFilterSpecialNeeds();
      this.shouldFilterSpecialtyCamps();
    },

    filterMatch: function(camp) {
      var match = true;
      for(var i=0; i<this.relevantFilters.length; i++) {
        if(this.relevantFilters[i].apply(this, [camp]) === false) {
          match = false;
          break;
        }
      }

      return match;
    },

    affiliationMatch: function(camp) {
      var match = false;
      ['conservative', 'orthodox', 'nondenominational', 
       'pluralistic', 'reconstructionist',
       'reform', 'zionist', 'other'].each(function(aff){
          if((this.filters[aff] == true) && (camp.fields[aff] == true))
            match = true;
        }.bind(this));
      return match;
    },

    genderMatch: function(camp) {
      var match = false;
      ['boys','girls','coed'].each(function(gender){
          if((this.filters[gender] == true) && (camp.fields[gender + '_sessions'] == true)) {
            match = true;
          }
      }.bind(this));
      return match;
    },

    specialNeedsMatch: function(camp) {
      var match = true;
      if ((this.filters['special_yes'] == true) && (camp.fields['special_needs'] == 0))
        match = false;
      return match;
    },

    specialtyCampsMatch: function(camp) {
      var match = false;
      none_checked = true;
      ['sports', 'visual_arts', 'dramatic_arts', 
       'arts_crafts', 'science_nature',
       'water_sports', 'hebrew', 'judaic_studies'].each(function(ss){
          if(this.filters[ss] == true) {
            none_checked = false;

            if(camp.fields[ss] == true)
              match = true;
          }
        }.bind(this));
      return none_checked || match;
    },

    regionMatch: function(camp) {
      var match = false;
      if(this.filters.regions.include(camp.fields.region)) {
        match = true;
      }

      return match;
    },

    valueFromInput: function(input) {
      this.filters[input.id] = input.checked;
    },

    fetchResults : function () {
      GDownloadUrl("/camp_data", function(data) {
        this.all_camps = eval( '(' + data + ')');
        this.callback(this.all_camps);
      }.bind(this));
    },

    searchResults : function(text) {
      this.results = [];
      for (i=0; i < this.all_camps.length; i++) {
        var regex = RegExp(text, 'i');
        matches = regex.exec(this.all_camps[i].fields.name);
        if (matches != null) {
          this.results.push(this.all_camps[i]);   
        }
      }
      return this.results;
   },

    filterResults : function () {
      this.recalculateFilters();
      this.chooseRelevantFilters();
      if(this.relevantFilters.length == 0) {
        return this.all_camps;
      }
      else {
        var results = [];
        for (var i=0; i < this.all_camps.length; i++) {
          if (this.filterMatch(this.all_camps[i])) {
            results.push(this.all_camps[i]);   
          }
        }
        return results;
      }
    }

});

var JewishCampMap = Class.create({

    initialize : function (element) {
      this.camps   = [];
      this.markers = {};
      this.gmap = new GMap2($(element));
      this.gmap.setCenter(new GLatLng(38,-75),3);
      this.gmap.addControl(new GLargeMapControl());
      return this.gmap;
    },

    update : function(results, func) {
      this.camps = results;
      this.markCamps();
      if(arguments[1]) {
        func();
      }
    },

    panToRegion : function (region) {
      this.gmap.panTo(new GLatLng(regions[region]['lat'],regions[region]['long']));
    },

    getCamps : function() {
      return this.camps;
    },
    
    addMarker : function (marker) {
      this.gmap.addOverlay(marker);
    },

    clearMarkers : function () {
      this.gmap.clearOverlays();
    },

    getCampByPK : function(pk) {
      for (i=0; i < this.camps.length; i++) {
        if (this.camps[i].pk == pk) {
          return this.camps[i];
        }
      }
    },

    showBubble : function(pk) {
      var marker = this.markers[pk];
      marker.openInfoWindowHtml(this.bubbleHTML(this.getCampByPK(pk)));
    },

    bubbleHTML : function(camp) {
      var html = $('map_bubble').innerHTML.replace(/#%7B([a-zA-Z0-9_-]+)%7D/gi, "#{$1}");

      var template = new Template(html);
      return template.evaluate(crl.campJsonData(camp));
    },

    markCamp : function (camp) {
      var point = new GLatLng(camp.fields.latitude, camp.fields.longitude);
      var fjcIcon = new GIcon(G_DEFAULT_ICON);

      fjcIcon.iconSize = new GSize(22,28);
      fjcIcon.image =  MAP_MARKER_URL;  
      fjcIcon.shadowSize = new GSize(33,29);
      fjcIcon.shadow =  MAP_MARKER_SHADOW_URL;
      markerOptions = { icon:fjcIcon };
      var marker = new GMarker(point, markerOptions);
      GEvent.addListener(marker, "click", function() {
        marker.openInfoWindowHtml(this.bubbleHTML(camp));
        accordion.expandByNum( camp.pk + '');
      }.bind(this));

      this.gmap.addOverlay(marker);
      return marker;
    },

    markCamps : function () {
      this.clearMarkers();
      for (i=0; i < this.camps.length; i++) {
        this.markers[this.camps[i].pk] = this.markCamp(this.camps[i]); 
      }
    }

});

function updateMap() {
  fm.recalculateFilters();
  results = fm.filterResults();
  crl.update(results);
  map.update(results);
  $('update_spinner').setStyle({display: 'none'});
}

function resetSearch() {
  $('camp_search_text').value = '';
  deleteCookie('camp_search_text');
  deleteCookie('camp_search_filters');
  $$('.affiliation').each(function(el) { el.checked = true; });
  $$('.gender').each(function(el) { el.checked = true; });
  $$('.specialty').each(function(el) { el.checked = false; });
  $('special_no').checked = true;
  $('region').value = "can_us";
  accordion.expandByNum( $$('div.accordion_toggle')[0].id + '');
  
  map.update(all_camps);
  crl.update(all_camps);
  map.panToRegion('can_us');
}

function searchByName(ev) {
	saveCampSearchText();
  if(ev) { ev.preventDefault(); }
  var search_text = $('camp_search_text').value;
  if(!(search_text.blank())) {
    camps = fm.searchResults(search_text);
    crl.update(camps);
    map.update(camps);
  }
  else {
    //resetSearch();
  }
} 

function saveCampSearchText() {
  var search_text = $('camp_search_text').value;
  if(!(search_text.blank())) {
    setCookie('camp_search_text', search_text);
  }
}

function restoreCampSearchText() {
  var search_text = getCookie('camp_search_text') || "";
  if(search_text && !(search_text.blank())) {
    $('camp_search_text').value = search_text;
  }
}

function initialize(callback) {
  if (GBrowserIsCompatible()) {
    map =  new JewishCampMap('map_canvas');
    crl = new CampResultsList();

    fm  =  new FilterManager(function(camps) {
      map.update(camps);
      crl.update(camps);
      map.panToRegion('can_us');
    });
    callback();
  }
}

document.observe('dom:loaded', function(){

  if($('map_canvas')) {
    initialize(function() {
      restoreCampSearchText();
      searchByName(false); 
    });
  }

  $$('.thumbs li a').each(function(el) {
    new PopUp(el, $('overlay_gallery'), { centered: true, modal: true });
    new SlideShow(0, $('overlay_gallery'), $$('#overlay_gallery .slide'), 4);
  });

  if($('overlay_filter'))  {
    new PopUp($('btn_filter_search'), $('overlay_filter'), { slide: true });
  }

  if($('overlay_help'))  {
    new PopUp($('btn_needhelp'), $('overlay_help'));
  }

  $('apply_filter').observe('click', function(ev) {
	  //Effect.Fade('update_spinner',{ duration: 1.0, from: 0, to: 1 });
	  $('update_spinner').setStyle({display: 'block'});
	  accordion.expandByNum( $$('div.accordion_toggle')[0].id + '');
	  setTimeout("updateMap()",100);
  

  });

  if($('camp_search_btn')) {
    $('camp_search_btn').observe('click', searchByName);
  }

  $('camp_search_text').observe('keydown', function(ev) {
    if(ev.keyCode == 13) {
      Event.stop(ev);
      
      searchByName(ev);
    }
  });

  $('reset_search').observe('click', function() {
    resetSearch();
  });

});
