/*
Script: supporters.js.php
    Contains classes for supporters and their properties.

Requires:
    Google maps
    MooTools
*/


/*
Class: Supporter
    Represents a supporter. Properties are not set by initiliaze() but need to
    be set before using Supporter's methods.

Properties:
    id
    addresses - An array of Addresses.
    commitments - An array of Commitments.
    firstname - First name.
    level - Expertise level.
    language - An array of locale strings for the supported languages.    
*/
var Supporter = new Class({
  
  /*
  Property: initialize
      Initialize the supporter. If the commitments and addresses properties are
      set, they must contains objects with Commitment and Address's properties.
      Elements of these arrays are extended with Commitment.prototype and
      Address.prototype before intialize is invoked on them. On return, the
      elements in commitments and addresses are Commitment and Address
      instances.
  */
  initialize: function()
  {
    if(this.commitments && $type(this.commitments)=='array')
    {
      this.commitments.forEach(function(commitment)
      {
        $extend(commitment, Commitment.prototype);
        commitment.initialize();
      });
    }
    else
    {
        this.commitments = [];
    }
    if(this.addresses && $type(this.addresses)=='array')
    {
      this.addresses.forEach(function(address)
      {
        $extend(address, Address.prototype);
        address.initialize();
      });
    }
    else
    {
        this.addresses = [];
    }
  },

  /*
  Property: getMarkers
      Returns the GMarkers for this supporter. One for each of this supporter's
      addresses.
  */
  getMarkers: function()
  {
    if(this.markers)
      return this.markers;
    
    this.markers = [];
    var supporter = this;
    this.addresses.forEach(function(address)
    {
      if(!address.marker)
      {
        address.marker = new GMarker(address.getPoint(), {"icon": supporter.getIcon()});
        GEvent.addListener(address.marker, "click", function() {
          this.openInfoWindow(supporter.getInfoWindow(address));
        });
      }
      supporter.markers.push(address.marker);
    });
    return supporter.markers;
  },

  getIcon: function()
  {
    if(!$defined(Supporter.icons))
    {
      icons = ['user']//, 'user_red', 'user_orange', 'user_green'];
      Supporter.icons = [];
      for (i=0;i<icons.length;i++)
      {
        icon = new GIcon();
        icon.image = 'http://map.ubuntu-be.org//images/'+icons[i]+'.png';
        icon.iconSize = new GSize(22, 25);
        icon.iconAnchor = new GPoint(8, 8);
        icon.infoWindowAnchor = new GPoint(8, 8);
        Supporter.icons[i] = icon;
      }
    }
    return Supporter.icons[this.id % Supporter.icons.length];
  },
  
  /*
  Property: getInfoWindow
      Returns a DOM element to display (short) information about a supporter
      at the given address.
  
  Arguments:
      address - An Address. If undefined or not one of the supporter's
      addresses, the first supporter's address is used.
  
  TODO:
      Add support for supporter without
        - address
        - level
        - language
        - commitment
  */
  getInfoWindow: function(address)
  {
    if(!$defined(address) || !this.addresses.contains(address)) address = this.addresses[0];
    if(!this.infoWindow) this.infoWindow = [];
    if(!this.infoWindow[address])
    {
      var infoWindow = new Element('div');
      this.infoWindow[address] = infoWindow;
      var infoHTML = this.firstname + ' (' + mapLevel(this.level) + ')<br/>';
      infoHTML += address.street + ', ' + address.city + '<br/>';
      infoHTML += 'Ik spreek ' + ' ' + textList(this.language.map(mapLocale)) + '<br/>';
      infoHTML += 'Vraag mij naar:<br />';
      infoWindow.setHTML(infoHTML);
      var ul = new Element('ul');
      supporter = this;
      this.commitments.forEach(function(commitment)
      {
        var li = new Element('li');
        var a = new Element('a');
        a.setProperty('href', 'http://map.ubuntu-be.org/index.php/supporters/contact/'+supporter.id+'/'+commitment.type);
        a.appendText(commitment.getLinkText());
        li.appendChild(a);
        ul.appendChild(li);
      });
      infoWindow.appendChild(ul);
    }
    return this.infoWindow[address]
  }
});

/*
Function Supporter.fromJson
    Returns an array of Supporter from a JSON array of objects. The JSON array
    is parsed. Each elements is extend with Supporter.prototype then it's
    initialize method is invoked. JSON objects in the array must have
    Supporter's properties defined.
       
External:
    supporters - A JSON array of objects.

*/
Supporter.fromJson = function(supporters)
{
    supporters = supporters.parseJSON();
    return supporters.map(function(supporter) 
    {
        supporter = $extend(supporter, Supporter.prototype);
        supporter.initialize();
        return supporter;
    });
}


/*
Function: fromHcard
    Returns a Supporter instance from a DOM element annotated with the hCard
    microformat. The element must contains an fn element with a given-name and
    one or more adr element. Each adr element must contains a geo element with
    an latitude and longitude element. If el has an id attribute, it's value
    is used as supporter id.
    !!! WIP !!!
    
Arguments:
    el - A DOM element annotated with the hCard microformat. 
*/
Supporter.fromHcard = function(el)
{
  el = $(el);
  if(el && el.hasClass('vcard'))
  {
    var supporter = new Supporter();
    var id = el.getProperty('id');
    if(id && id!=='')
        supporter.id = id;
    var fn = el.getElement('.fn');
    if(fn)
    {
        var givenName = fn.getElement('.given-name');
        if(givenName)
            supporter.firstname = givenName.getValue() || givenName.textContent;
    }
    el.getElements('.adr').forEach(function(adr)
    {
        var address = new Address();
        var geo = adr.getElement('.geo');
        if(geo)
        {
            var latitude = geo.getElement('.latitude');
            address.latitude = latitude.getValue() || latitude.textContent;
            var longitude = geo.getElement('.longitude');
            address.longitude = longitude.getValue() || longitude.textContent;
        }
        supporter.addresses.push(address);
    });
    return supporter;   
  }
}

/*
Function: Supporter.fromHcards
    Returns an array of supporters from the hCard annotated elements contained
    in el. If $(el) returns false, document is used.
    !!! WIP !!!

Arguments:
    el - A DOM element containing elements annotated with the hCard microformat. 
*/
Supporter.fromHcards = function(el)
{
    el = $(el) || document;
    return el.getElements('.vcard').map(Supporter.fromHcard);
}

/*
Class: Commitment

Properties:
    id
    start_date
    end_date
    type - Type of the commitments.
*/
var Commitment = new Class(
{
  initialize: function()
  {
  },

  /*
  Property: getLinkText
      Returns the text to display when linking to this commitments.
  */
  getLinkText: function()
  {
    switch(this.type)
    {
      case "distribute": return "een gratis Ubuntu-installatieset";
      case "demo": return "een gratis Ubuntu-demonstratie";
      case "install": return "gratis hulp bij uw eerste installatie";
      default: return this.type;
    }
  }
});

/*
Class: Address
    Represents an address.
    
Properties:
    id
    street
    city
    zipcode
    latitude
    longitude
*/
var Address = new Class(
{

  initialize: function()
  {
  },


  /*
  Property: getPoint
      Returns the GLatLng for this address coordinates.
  */
  getPoint: function()
  {
    if(!this.point)
      this.point = new GLatLng(this.latitude, this.longitude);
    return this.point;
  }
});
