/* map.js
 * December 22, 2009 Jon Suderman
 * requires prototype
 *
 *--------------------------------------------------------------------------*/
 
var Map = Class.create({
  
  categories  : {},
  groups      : {}, 
  
  initialize: function(container, xml){
    
    // Verify container and set
    if (!$(container)) { return false }
    this.container = container
    this.map_image = container + '_map'
    this.map_legend = container + '_legend'
    // Request XML and convert to JSON
    new Ajax.Request(xml, { 
      method: 'get', 
      onSuccess: function(transport) {       
        this.build_map(XMLObjectifier.xmlToJSON(transport.responseXML)) 
      }.bind(this)
    })       
    
  },
  
  build_map: function(map_data){
    var template = '<div id="#{map_image}" class="map_image" style="position:relative;">'+
                       '<img src="#{map_image_src}" />'+
                       '#{map_points}'+
                     '</div>'+
                     '<div id="#{map_legend}" class="map_legend">#{map_groups}</div>'
                     
    template = template.interpolate({ 
      map_image     : this.map_image,
      map_image_src : map_data.attr('image'),
      map_legend    : this.map_legend,
      map_groups    : this.build_groups(map_data),
      map_points    : this.build_points(map_data)
      
    })
    $(this.container).insert(template)
    
    this.observe_legend_links()
    this.observe_point_links()
    
  },

  build_groups: function(map_data){
   
    var group_template =  '<div class="map_group" style="float:left;">'+
                            '<h3>'+
                              '<a href="#toggle" class="map_group_link on #{category_classes}" rel="#{category_classes}" title="#{group_title}">'+
                                '#{group_title}'+
                              '</a>'+
                            '</h3>'+
                            '<ul>#{group_categories}</ul>'+
                          '</div>'
                          
    var category_template = '<li>'+
                              '<a href="#toggle" class="map_category_link on #{category_class}" title="#{category_title}" rel="#{category_class}">'+
                                '<img src="#{category_icon}" /> '+
                                '#{category_title}'+
                              '</a>'
                            '</li>'
    var legend = $A(map_data.group).collect(function(group){      
      // Ad this group to the hash
      this.groups[group.attr('title')] = []      
      var categories = $A(group.category).collect(function(category){
        // Add this category to the hash
        this.categories[category.attr('id')] = { 
          title : category.attr('title'), 
          icon  : category.attr('icon'), 
          group : group.attr('title') 
        }
        // Add this category to the array of the group hash
        this.groups[group.attr('title')].push(category.attr('id'))
        return category_template.interpolate({          
          category_icon : category.attr('icon'),
          category_title: category.attr('title'),
          category_class: 'category_' + category.attr('id')
        })
      }.bind(this))
      return group_template.interpolate({
        group_title     : group.attr('title'),
        group_categories: categories.join(''),
        category_classes: 'category_' + $A(group.category).pluck('@id').join(' category_')
      })
    }.bind(this))
   // Clean-up
   map_data = null
   group_template = null
   category_template = null
   categories = null
   
   return legend.join('')
  },  
 
  
  build_points: function(map_data){
   
    var point_template =  '<a href="#{point_link}" class="map_point #{point_clickable} #{category_classes}" title="#{point_title}" style="dislay:block; position: absolute; left:#{x}px; top:#{y}px;">'+
                            '<ul>#{point_categories}</ul>'+
                            '<h3>#{point_title}</h3>#{point_content}'+
                          '</a>'
                          
    var category_template = '<li class="point_category on #{category_class}" category="#{category_class}" style="float:left;">'+
                              '<img title="#{category_title}" src="#{category_icon}" /> '+
                            '</li>'
    var points = $A(map_data.point).collect(function(point){
      var categories = $A(point.category).collect(function(category){
      
        return category_template.interpolate({
          category_icon   : category.attr('icon') || this.categories[category.attr('id')].icon,
          category_title  : category.attr('title') || this.categories[category.attr('id')].title,
          category_class  : 'category_' + category.attr('id')
        })
      }.bind(this))
      return point_template.interpolate({
        point_title     : point.attr('title'),
        x               : point.attr('x'),
        y               : point.attr('y'),
        point_link      : point.attr('url') || '#point',
        point_content   : (point.val()) ? '<div class="point_content" style="display:none;">' + point.val() + '</div>' : '',
        point_clickable : (point.val() || point.attr('url')) ? 'clickable' : '',
        category_classes: 'category_' + $A(point.category).pluck('@id').join(' category_'),
        point_categories: categories.join('')
      })
    }.bind(this))   
   // Clean-up
   map_data = null
   point_template = null
   category_template = null
   categories = null
   
   return points.join('') 
  },
  
  // Click events
  observe_legend_links: function(){
    var all_legend_links = $(this.map_legend).select('a.map_category_link, a.map_group_link')    
    
    all_legend_links.each(function(a){
      a.observe('click', function(event){
        event.stop()
        
        var on_off = (a.hasClassName('on')) ? 'off' : 'on'        
        var selector = 'li.' + a.rel.split(' ').join(', li.')
        var all_point_categories = $(this.map_image).select(selector)
        all_point_categories.each(function(point_category){
          this.toggle_category(point_category, on_off)
        }.bind(this))
        
      }.bind(this))
    }.bind(this))  
  },
  
  observe_point_links: function(){
    var all_point_links = $(this.map_image).select('a.clickable')
    
    all_point_links.each(function(a){
      
      // Set target to blank to pop new with (only used if URL)
      a.target = '_BLANK'
      
      a.observe('click', function(event){
        
        // If there's content, ignore the URL and show dialog
        if (a.down('.point_content')) {
          event.stop()
          var dialog = new S2.UI.Dialog({
            title: a.down('h3').innerHTML,
            content: a.down('.point_content').innerHTML,
            buttons: false
          });
          dialog.open();          
        }
      }.bind(this))
    }.bind(this))
  },
 
  
  toggle_category: function(point_category, on_off){
    var group_category = $(this.map_legend).select('a.' + point_category.readAttribute('category'))
    
    // Hide the category
    if (on_off=='off') {
      point_category.removeClassName('on').addClassName('off').hide()
      group_category.invoke('removeClassName','on').invoke('addClassName','off').invoke('setStyle',{opacity:.5})      
      
    // Show the category
    } else if (on_off=='on') {
      point_category.removeClassName('off').addClassName('on').show()            
      group_category.invoke('removeClassName','off').invoke('addClassName','on').invoke('setStyle',{opacity:1})
    }
    
    // Show or hide the group link
    var map_group = group_category.first().up('.map_group')
    var remaining_categories = map_group.select('li a.on')
    
    if (remaining_categories.size() > 0) {
      map_group.down('a.map_group_link').setStyle({opacity:1})
    } else {
      map_group.down('a.map_group_link').setStyle({opacity:.5})
    }
    
    // Show or hide the point
    var map_point = point_category.up('a.map_point')
    var remaining_categories = map_point.select('li.on')
    
    if (remaining_categories.size() > 0) {
      map_point.show()
    } else {
      map_point.hide()
    }
    
    // Clean-up
    group_category = null
    point_category = null
    on_off = null
    map_group = null
    remaining_categories = null
  }  
  
})
