var Locations = function(ls){
  l = this;
  this.name = "Locations";
  this.locations = ls;
  this.markerCounts = 0;
  var map = null,
      infowindow = new google.maps.InfoWindow(),
      default_location = new google.maps.LatLng( 24.8043107, 121.03042159999995 ),
      infowindow_template = "<div class='title'></div><div class='image'><img class='thumbnail' src='' /></div>",
      markers = [];


  var initialize = function() {
    google.maps.visualRefresh = true;
    var location = ( l.locations.length ? new google.maps.LatLng( l.locations[0].latitude, l.locations[0].longitude ) : default_location ),
        mapOptions = {
          zoom: 16,
          center: location,
          mapTypeId: google.maps.MapTypeId.ROADMAP
        };

    map = new google.maps.Map( document.getElementById('map'), mapOptions );

    for( i = 0; i < l.locations.length; i++ ){
      markers.push( addMarker( new google.maps.LatLng(l.locations[i].latitude, l.locations[i].longitude), l.locations[i].color, i, function( index ){

      }) );
    }

  }

  var addMarker = function( location, pinColor, index, markerCallback ){

    var pin = getPin(( pinColor.substr( 0, 1 ) == "#" ? pinColor.replace("#","") : pinColor )),
        marker = new google.maps.Marker({
                        map: map,
                        icon: pin.image,
                        shadow: pin.shadow,
                        position: location,
                        zIndex: 10
                  });

    google.maps.event.addListener( marker, 'click', function() {

      infowindow.setContent( getTemplate( index ) );
      infowindow.open( map, marker );
      if( typeof markerCallback == "function" )
        markerCallback.call( this, index );

    });

    l.markerCounts++;
    return {"marker" : marker, "category_id" : l.locations[index].category_id};
  }



  var getTemplate = function( obj ){

    var object = ( typeof obj == "number" ? l.locations[obj] : ( typeof obj == "object" ? obj : null ) );

    if ( object ){

      var template = $( "<div></div>" );
      template.html( infowindow_template );
      template.find( '.title' ).text( object.name );
      template.find( "img.thumbnail" ).attr( "src", object.file.thumb.url );
      return template.html();

    }else{

      throw new InvalidObjectError();
    }

  }

  var getPin = function( color ){

    var pinImage = new google.maps.MarkerImage("http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=%E2%80%A2|" + color,
        new google.maps.Size(21, 34),
        new google.maps.Point(0,0),
        new google.maps.Point(10, 34));

    var pinShadow = new google.maps.MarkerImage("http://chart.apis.google.com/chart?chst=d_map_pin_shadow",
        new google.maps.Size(40, 37),
        new google.maps.Point(0, 0),
        new google.maps.Point(12, 35));

    return {"image":pinImage,"shadow":pinShadow};
  }

  this.getMarker = function( index ){
    return markers[index];
  }
  this.getAllMarkers = function(  ){
    return markers;
  }

  this.clearFilter = function(){
    var m = l.getAllMarkers();
    for( i = 0; i < m.length; i++ ){
      m[i].marker.setVisible(true);
    }
  }

  this.filterMarkers = function( categories ){
    var filtered = [],
        m = l.getAllMarkers();

    for( i = 0; i < m.length; i++ ){
      m[i].marker.setVisible(false);
    }
    for( i = 0; i < categories.length; i++ ){
      filtered = filtered.concat(m.filter(function(a){return a.category_id == categories[i]}));
    }
    for( i = 0; i < filtered.length; i++ ){
      filtered[i].marker.setVisible(true);
    }
    return filtered;
  }
  initialize();

}

var InvalidObjectError = function(){
  this.name = "InvalidObjectError";
  this.message = "Object not valid";
}

InvalidObjectError.prototype = new Error();
InvalidObjectError.prototype.constructor = InvalidObjectError;
