
Number.prototype.ordinal = function () {
	return this + (
		(this % 10 == 1 && this % 100 != 11) ? 'st' :
		(this % 10 == 2 && this % 100 != 12) ? 'nd' :
		(this % 10 == 3 && this % 100 != 13) ? 'rd' : 'th'
	);
};

var VoteLookup = {
  mode: 'yes-only', /* 'yes-phone', 'all' */
  govTrackRegionsUrl: 'http://www.govtrack.us/perl/wms/list-regions.cgi?dataset=http://www.rdfabout.com/rdf/usgov/congress/house/110&fields=area&format=json&json_callback=?&uri=',
  districtRegionsUrl: 'http://www.rdfabout.com/rdf/usgov/geo/us/' ,
  marker: '/displayer/images/generic.png',
  markerShadow: '/displayer/images/generic-shadow.png',
  imagePrefix: '/vote-lookup/images/',
  stateMap: {"VA":"Virginia",
   "ND":"North Dakota",
   "NY":"New York",
   "AL":"Alabama",
   "RI":"Rhode Island",
   "NE":"Nebraska",
   "MN":"Minnesota",
   "MD":"Maryland",
   "HI":"Hawaii",
   "DE":"Delaware",
   "CO":"Colorado",
   "PR":"Puerto Rico",
   "WY":"Wyoming",
   "MO":"Missouri",
   "ME":"Maine",
   "IA":"Iowa",
   "MP":"Northern Mariana Islands",
   "GU":"Guam",
   "OR":"Oregon",
   "OH":"Ohio",
   "KY":"Kentucky",
   "IL":"Illinois",
   "AZ":"Arizona",
   "TX":"Texas",
   "TN":"Tennessee",
   "NH":"New Hampshire",
   "GA":"Georgia",
   "MH":"Marshall Islands",
   "SC":"South Carolina",
   "IN":"Indiana",
   "ID":"Idaho",
   "SD":"South Dakota",
   "PA":"Pennsylvania",
   "OK":"Oklahoma",
   "NJ":"New Jersey",
   "MS":"Mississippi",
   "MI":"Michigan",
   "FL":"Florida",
   "CT":"Connecticut",
   "AR":"Arkansas",
   "PW":"Palau",
   "FM":"Federated States of Micronesia",
   "AS":"American Samoa",
   "WI":"Wisconsin",
   "MT":"Montana",
   "VI":"Virgin Islands",
   "VT":"Vermont",
   "NV":"Nevada",
   "KS":"Kansas",
   "CA":"California",
   "DC":"District of Columbia",
   "WV":"West Virginia",
   "UT":"Utah",
   "NM":"New Mexico",
   "MA":"Massachusetts",
   "WA":"Washington",
   "NC":"North Carolina",
   "LA":"Louisiana",
   "AK":"Alaska"},
  doError: function(err) {
    this.errorDiv.text(err);
    this.errorDiv.slideDown();
    this.toggleSubmit(true);
  },
  toggleSubmit: function(onoff) {
    if (onoff) {
      this.addrSubmit.attr('value', this.originalSubmitText);
      this.addrSubmit.attr('disabled', false);
    } else {
      this.addrSubmit.attr('value', 'Loading...');
      this.addrSubmit.attr('disabled', true);
      this.errorDiv.slideUp();
    }
  },
  addMember: function(member, vote) {
    var div = jQuery('<div class="vote-lookup-member"/>');
    if (member.title == 'Rep') {
      div.addClass('vote-lookup-rep');
    } else if (member.title == 'Sen') {
      div.addClass('vote-lookup-sen');
    }
    var table = jQuery('<table cellpadding="0" cellspacing="0" border="0" class="vote-lookup-member-table" />');
    var tbody = jQuery('<tbody/>');
    var tr = jQuery('<tr/>');
    var imgTd = jQuery('<td class="image" />');
    var textTd = jQuery('<td class="text" />');
    var img = jQuery('<img src="' + this.imagePrefix + member.bioguide_id +
      '.jpg" class="vote-lookup-member-image"/>');
    var name = jQuery('<div class="vote-lookup-member-name"/>');
    var nameStr = member.title + '. ' + member.firstname + ' ' + member.lastname + ' (' + member.party + ')';
    name.text(nameStr);
    var voted = jQuery('<div class="vote-lookup-member-vote"/>');
    voted.text('Vote: ');
    var positionClass = 'vote-lookup-member-position-' + vote.toLowerCase().replace(/\s+/, '-');
    var position = jQuery('<span class="vote-lookup-member-position"/>');
    position.addClass(positionClass);
    position.text(vote);
    var phone = jQuery('<div class="vote-lookup-member-phone" />');
    phone.text('Phone: ' + member.phone);
    /* construct member div */
    div.appendTo(this.membersDiv);
    table.appendTo(div);
    tbody.appendTo(table);
    tr.appendTo(tbody);
    imgTd.appendTo(tr);
    img.appendTo(imgTd);
    textTd.appendTo(tr);
    name.appendTo(textTd);
    position.appendTo(voted);
    voted.appendTo(textTd);
    if (member.phone.length >= 10 && (this.mode != 'yes-phone' || vote == 'Yes')) {
      phone.appendTo(textTd); 
    }
  },
  fullDistrict: function(stateAbbr, number) {
    numInt = parseInt(number);
    numStr = numInt.ordinal();
    if (numInt == 0) {
      numStr = 'At Large';
    }
    var state = this.stateMap[stateAbbr];
    return state + "&rsquo;s " + numStr;
  },
  load: function(vote, id) {
    var self = this;
    google.load("maps", "2.x");
    google.setOnLoadCallback(function() {
      google.maps.MAP_TYPE = google.maps.NORMAL_MAP;
      google.maps.SATELLITE_TYPE = google.maps.SATELLITE_MAP;
      self.geocoder = new google.maps.ClientGeocoder();
      self.container = jQuery('#' + id);
      self.addrForm = self.container.find('.vote-lookup-addr-form').eq(0);
      self.addrInput = self.addrForm.find('.vote-lookup-addr-input').eq(0);
      self.addrSubmit = self.addrForm.find('.vote-lookup-addr-submit').eq(0);
      self.originalSubmitText = self.addrSubmit.attr('value');
      self.resultsDiv = self.container.find('.vote-lookup-results').eq(0);
      self.membersDiv = self.resultsDiv.find('.vote-lookup-members').eq(0);
      self.mapDiv = self.container.find('.vote-lookup-map').eq(0);
      var customIcon = new google.maps.Icon();
      customIcon.image = self.marker;
      customIcon.shadow = self.markerShadow;
      customIcon.iconSize = new google.maps.Size(24, 35);
      customIcon.shadowSize = new google.maps.Size(44, 35);
      customIcon.iconAnchor = new google.maps.Point(12, 35);
      customIcon.infoWindowAnchor = new google.maps.Point(12, 1);
      self.districtName = self.resultsDiv.find('.vote-lookup-district-name').eq(0);
      self.addrToggle = self.resultsDiv.find('.vote-lookup-addr-toggle').eq(0);
      self.errorDiv = self.container.find('.vote-lookup-error').eq(0);
      self.addrInput.select();
      self.addrForm.bind('submit', function(e) {
        e.preventDefault();
        self.toggleSubmit(false);
        self.resultsDiv.slideUp();
        var addr = self.addrInput.attr('value');
        self.geocoder.getLocations(addr, function(res) {
          if (res['Status']['code'] == 200) {
            var placemark = res['Placemark'][0];
            var accuracy = placemark['AddressDetails']['Accuracy'];
            if (accuracy >= 8) {
              var full = placemark['address'];
              var point = placemark['Point'];
              var lng = point['coordinates'][0];
              var lat = point['coordinates'][1];
              jQuery.getJSON("/vote-lookup/php/proxy.php", {latitude: lat, longitude: lng},
                function(data) {
                  if (data.response && data.response.districts && data.response.districts.length == 1) {
                    var district = data.response.districts[0]['district'];
                    var state = district['state'];
                    var number = district['number'];
                    var fullDistrictName = self.fullDistrict(state, number) + ' District';
                    jQuery.getJSON('/vote-lookup/votes/' + vote + '.json', function(voteData) {
                      if  (voteData.name && voteData.lookup && voteData.lookup[state]) {
                        var stateLookup = voteData.lookup[state];
                        var voteName = voteData.name;
                        var members = [stateLookup[number],
                          stateLookup['Senior Seat'], stateLookup['Junior Seat'], stateLookup['Jr']];
                        var realMembers = [];
                        jQuery.each(members, function(i, member) {
                          if (member && (self.mode != 'yes-only' || member[1] == 'Yes')) {
                            realMembers.push(member);
                          }
                        });
                        var addedMembers = [];
                        var memberLookup = {};
                        self.membersDiv.empty();
                        self.districtName.html(fullDistrictName);
                        self.addrToggle.show();
                        self.addrToggle.bind('click', function(e) {
                          e.preventDefault();
                          self.addrForm.show();
                          self.addrInput.focus();
                          self.addrInput.select();
                          jQuery(this).hide();
                        })
                        if (realMembers.length > 0) {
                          jQuery.each(realMembers, function(i, member) {
                            var bioId = member[0];
                            var votePosition = member[1];
                            jQuery.getJSON('/vote-lookup/members/' + bioId + '.json', function(memberData) {
                              memberLookup[bioId] = [memberData, votePosition];
                              addedMembers.push(member);
                              if (addedMembers.length == realMembers.length) {
                                jQuery.each(realMembers, function(j, loadedMember) {
                                  var memberObj = memberLookup[loadedMember[0]];
                                  self.addMember(memberObj[0], memberObj[1]);
                                });
                                self.mapDiv.empty();
                                self.resultsDiv.slideDown('normal', function(){
                                  self.map = new google.maps.Map2(self.mapDiv[0]);
                                  var latlng = new google.maps.LatLng(lat, lng);
                                  self.map.addControl(new google.maps.SmallZoomControl());
                                  var uri = self.districtRegionsUrl + state.toLowerCase();
                                  if (number != 0) {
                                    uri +=  '/cd/110/' + number;
                                  }
                                  var url = self.govTrackRegionsUrl + uri;
                                  console.log(url);
                                  jQuery.getJSON(url, function(data) {
                                    var maxMatch = 0;
                                    jQuery.each(data, function(i, item) {
                                      if (item[0] == uri && item[1] > maxMatch) {
                                        maxMatch = item[1];
                                      }
                                    });
                                    console.log('area = ' + maxMatch);
                                    var zoomLevel = 14 - Math.round(Math.log(Math.sqrt(maxMatch))/Math.log(2));
                                    console.log('zoomLevel = ' + zoomLevel);
                                    self.map.setCenter(latlng, zoomLevel);
                                    var WMS_URL = 'http://www.govtrack.us/perl/wms-cd.cgi?';
                                    var G_MAP_LAYER_FILLED = createWMSTileLayer(WMS_URL, "cd-filled,district=" + state + number, null, "image/gif", null, null, null, .25);
                                    var G_MAP_LAYER_OUTLINES = createWMSTileLayer(WMS_URL, "cd-outline,district=" + state + number, null, "image/gif", null, null, null, .66, "Data from GovTrack.us");
                                    var G_MAP_OVERLAY = createWMSOverlayMapType([G_NORMAL_MAP.getTileLayers()[0], G_MAP_LAYER_FILLED, G_MAP_LAYER_OUTLINES], "Overlay");
                                    self.map.addMapType(G_MAP_OVERLAY);
                                    self.map.setMapType(G_MAP_OVERLAY);
                                    var m = new google.maps.Marker(latlng, {icon: customIcon});
                                    self.map.addOverlay(m);
                                  });
                                });
                              }
                            });
                          })
                          self.addrForm.slideUp('normal', function() {
                            self.toggleSubmit(true);
                          });
                        } else {
                          /* no relevant votes found */
                          self.doError('No ' + (self.mode == 'yes-only' ? 'yes ' : '') + 
                            'votes found for that address.');
                        }
                      } else {
                        /* vote not found */
                        self.doError('No votes found for that address.');
                      }
                    });
                  } else {
                    /* district not found */
                    self.doError('No district found for that address.');
                  }
                });
            } else {
              self.doError('Address not specific enough. Please provide a full street address.')
            }
          } else {
            /* address not found */
            self.doError('Address not found. Please try again.');
          }
        });
      });
    });
  }
};
