+function (w) {
  "use strict";

  var map;
  var markerManager;
  var geocoder;
  var infowindow;
  var markers;
  var marker;
  var markersArray = [];
  var recipientId = 0;
  var latitude = 0;
  var longitude = 0;
  var query = {};
  var url = "https://fyi2.airprojects.org";

  function attachMessageInfoWindow(marker, number) {
      google.maps.event.addListener(marker, 'click', function () {
          var latLng = new google.maps.LatLng(marker.Y, marker.X);
          marker.position = latLng;
          showRecipientInfo(marker.RecipientId, marker.RecordType, marker);
      });
  }

  function timeoutMain() {
      jQuery('#blockMainMessage').html('AJAX Timeout');
  }

  function blockMain() {
      jQuery('#searchControls').block({ message: jQuery('#blockMainMessage'),
          overlyCSS: { backgroundColor: '#F1F2F7' }
      });
  }

  function unblockMain() {
      jQuery('#searchControls').unblock({ fadeOut: 0 });
  }

  function updateInfo(info, level = 'Notice') {
      var c = 'alert-'+level.toLowerCase();
      var infoContent = '<div class="alert alert-block '+c+'"><strong class="element-invisible">'+level+':</strong>  ' + info + '</div>';

      jQuery("#info").html(infoContent).show();
  }

  function clearInfo() {
      jQuery("#info").html("").hide();
  }

  function clearOverlays() {
      if (infowindow) { infowindow.close(); }

      jQuery(markersArray).each(function (index, item) {
          item.setMap(null);
      });
  }

  function getTopicFilters() {
      var filters = [];

      jQuery(".topicFilter:checked").each(function () {
          filters.push(jQuery(this).val());
      });

      return filters.join(',');
  }

  function getDepartmentFilters() {
      var filters = [];

      jQuery(".departmentFilter:checked").each(function () {
          filters.push(jQuery(this).val());
      });

      return filters.join(',');
  }

  function clearRecipients()
  {
      jQuery("#recipients tbody").html("");
  }

  function listRecipients(model) {
      jQuery('#mmc_download').remove();
      unblockMain();
      clearRecipients();

      if (model.RecipientInfos.length == 0) {
          updateInfo("No programs were found for the search criteria you provided.");

          return;
      }

      var tbody = jQuery("#recipients tbody");
      var rowcount = 0;
      var evenodd = 'none';

      jQuery(model.RecipientInfos).each(function (index, info) {
          if (rowcount % 2 === 0) { evenodd = 'odd'; } else { evenodd = 'even'; }
          tbody.append('<tr class="'+evenodd+'"></tr>');
          var tr = jQuery('tr:last', tbody);
          tr.append('<td><p class="mmc_tabular_title">' + info.T + '</p><p class="mmc_tabular_fai">Award: ' + info.FAI + '</p></td>');
          tr.append('<td>' + info.PD + '</td>');
          tr.append('<td>' + info.PN + '</td>');
          if (info.AN !== null && info.MAN.indexOf(info.AN) == -1)
              tr.append('<td><p class="mmc_tabular_dept">' + info.MAN + '</p><p class="mmc_tabular_agency">' + info.AN + '</p></td>');
          else
              tr.append('<td><p class="mmc_tabular_dept">' + info.MAN + '</p></td>');
          tr.append('<td>' + info.N + '</td>');
          tr.append('<td>' + info.A + '</td>');

          rowcount++;
      });

      jQuery('#recipients').css('display','block');
      jQuery('#recipients').prepend('<p style="text-align:right;"><a id="mmc_download" class="btn btn-primary" href="/mmc/api/download?StatusCode=200&Accuracy=4&Address='+query.address+'&Latitude='+query.latitude+'&Longitude='+query.longitude+'&ZipCode='+query.zipcode+'&Radius='+query.radius+'&Coordinates=&RecipientId=0&RecordType=0&RecipientInfos=&FederalAwardId=&Keyword='+query.keywords+'" target="_blank">Download results</a></p>')
  }

  function markMapCoordinates(model) {
      clearOverlays();

      if (model.Coordinates.length == 0) {
          unblockMain();
          updateInfo("No programs were found for the search criteria you provided.");

          return;
      }

      // If this is a keyword only search or a topic and department only search then determine if any of the result types were topped at 200 and display a message to the user letting them know that their results have been capped.
      if (model.Address.length == 0 && model.Keyword.length > 0 || model.Address.length == 0 && model.Keyword.length == 0)
      {
          var pwc = jQuery.grep(model.Coordinates, function (item) { return item.RT == 1 }).length;
          var swc = jQuery.grep(model.Coordinates, function (item) { return item.RT == 2 }).length;
          var cc = jQuery.grep(model.Coordinates, function (item) { return item.RT == 3 }).length;

          if (pwc >= 200 || swc >= 200 || cc >= 200)
          {
              updateInfo("Your requested combination of keywords and filters contains a large number of results, so the number of results returned below has been limited. To see the full set of results either enter an address or zip code or narrow your search.");
          }
      }

      var bounds = new google.maps.LatLngBounds();
      markers = new Array();

      //Add Markers.
      for (var i = 0; i < model.Coordinates.length; i++) {
          var latLng = new google.maps.LatLng(model.Coordinates[i].Y, model.Coordinates[i].X);

          marker = new google.maps.Marker({
              position: latLng,
              map: map,
              clickable: true
          });

          markersArray.push(marker);
          marker.setTitle(model.Coordinates[i].PTA);
          marker.RecipientId = model.Coordinates[i].Id;
          marker.RecordType = model.Coordinates[i].RT;
          marker.Y = model.Coordinates[i].Y;
          marker.X = model.Coordinates[i].X;
          attachMessageInfoWindow(marker, i);
          bounds.extend(latLng);
      }

      map.fitBounds(bounds);
      var zoomLevel = map.getZoom();

      if (zoomLevel > 18){
          map.setZoom(18);
      }
      else {
          map.setZoom(map.getZoom());
      }

      markers = null;
      unblockMain();
  }

  function showRecipientInfo(id, recordType, marker) {

      jQuery.ajax({
          url: "/mmc/api/GetRecipientInfos",
          data: {
              RecipientId: id,
              RecordType: recordType,
              keyword: jQuery("#keyword").val(),
              TopicFilters: getTopicFilters(),
              DepartmentFilters: getDepartmentFilters()
          },
          dataType: 'json',
          success: function (model) {
              recipientId = model.RecipientId;
              latitude = marker.X;
              longitude = marker.Y;

              if (infowindow) infowindow.close();

              infowindow = new google.maps.InfoWindow({
                  content: formatRecipientInfo(model.RecipientInfos),
                  size: new google.maps.Size(50, 50)
              });

              infowindow.open(map, marker);
          },
          error: function (jqXHR, textStatus, errorThrown) {
              unblockMain();
          }

      });
  }

  function formatRecipientInfo(recipientInfos) {

      var formatString = "No result found";

      if (recipientInfos != null && recipientInfos.length > 0) {

          if (recipientInfos.length > 1) {
              return formatMultipleRecipientInfo(recipientInfos);
          }
          else {
              return formatSingleRecipientInfo(recipientInfos);
          }
      }
      else {
          formatString = "No result found";
      }

      return formatString;
  }

  function formatSingleRecipientInfo(recipientInfos) {

      var formatString = "";

      formatString += "<p style='font-size:8pt;'>";

      if (recipientInfos[0].RT == 1) {

          if (recipientInfos[0].T)
              formatString += "<br /><strong>" + recipientInfos[0].T + "</strong>";

          if (recipientInfos[0].PD)
              formatString += "<br /><strong><i>Description:</i></strong> " + recipientInfos[0].PD;

          if (recipientInfos[0].PN)
              formatString += "<br /><strong><i>CFDA Program Number:</i></strong> " + recipientInfos[0].PN;

          if (recipientInfos[0].MAN)
              formatString += "<br /><strong><i>Department:</i></strong> " + recipientInfos[0].MAN;

          if (recipientInfos[0].AN)
              formatString += "<br /><strong><i>Funding Agency:</i></strong> " + recipientInfos[0].AN;

          if (recipientInfos[0].FAI)
              formatString += "<br /><strong><i>Award Number:</i></strong> " + recipientInfos[0].FAI;

          if (recipientInfos[0].N)
              formatString += "<br /><strong><i>Recipient:</i></strong> " + recipientInfos[0].N;

          if (recipientInfos[0].A)
              formatString += "<br /><strong><i>Recipient Address:</i></strong> <br />" + recipientInfos[0].A;

          //check if this primary award recipient has sub-awards.
          if (recipientInfos[0].HS > 0)
              formatString += "<br /><i>Show <a href=\"javascript:mmc.findSubAwardees('" + recipientInfos[0].FAI + "')\">sub-award recipients</a> in this state.</i> <br />";
      }
      else if (recipientInfos[0].RT == 2) {

          if (recipientInfos[0].T)
              formatString += "<br /><strong>" + recipientInfos[0].T + "</strong>";

          if (recipientInfos[0].PD)
              formatString += "<br /><strong><i>Description:</i></strong> " + recipientInfos[0].PD;

          if (recipientInfos[0].PN)
              formatString += "<br /><strong><i>CFDA Program Number:</i></strong> " + recipientInfos[0].PN;

          if (recipientInfos[0].MAN)
              formatString += "<br /><strong><i>Department:</i></strong> " + recipientInfos[0].MAN;

          if (recipientInfos[0].AN)
              formatString += "<br /><strong><i>Funding Agency:</i></strong> " + recipientInfos[0].AN;

          if (recipientInfos[0].FAI)
              formatString += "<br /><strong><i>Sub-Award Number:</i></strong> " + recipientInfos[0].FAI;

          if (recipientInfos[0].N)
              formatString += "<br /><strong><i>Sub-Award Grantee:</i></strong> " + recipientInfos[0].N;

          if (recipientInfos[0].A)
              formatString += "<br /><strong><i>Sub-Award Grantee Address:</i></strong> <br />" + recipientInfos[0].A;
      }
      else {

          if (recipientInfos[0].N)
              formatString += "<strong>" + recipientInfos[0].N + "</strong>";

          if (recipientInfos[0].PD)
              formatString += "<br /><strong><i>Description:</i></strong> " + recipientInfos[0].PD;

          if (recipientInfos[0].PN)
              formatString += "<br /><strong><i>CFDA Program Number:</i></strong> " + recipientInfos[0].PN;

          if (recipientInfos[0].MAN)
              formatString += "<br /><strong><i>Department:</i></strong> " + recipientInfos[0].MAN;

          if (recipientInfos[0].AN)
              formatString += "<br /><strong><i>Funding Agency:</i></strong> " + recipientInfos[0].AN;

          if (recipientInfos[0].FAI)
              formatString += "<br /><strong><i>Award Number:</i></strong> " + recipientInfos[0].FAI;

          if (recipientInfos[0].N)
              formatString += "<br /><strong><i>Recipient:</i></strong> " + recipientInfos[0].N;

          if (recipientInfos[0].A)
              formatString += "<br /><strong><i>Recipient Address:</i></strong> <br />" + recipientInfos[0].A;
      }

      formatString += "</p>";

      return formatString;
  }

  function formatMultipleRecipientInfo(recipientInfos) {

      var formatString = "";

      for (var i = 0; i < recipientInfos.length; i++) {

          if (i > 0)
          { formatString += "<hr />" }

          formatString += "<p style='font-size:8pt;'>";

          if (recipientInfos[i].RT == 1) {

              if (recipientInfos[i].T)
                  formatString += "<strong>" + recipientInfos[i].T + "</strong>";

              if (recipientInfos[i].PD)
                  formatString += "<br /><strong><i>Description:</i></strong> " + recipientInfos[i].PD;

              if (recipientInfos[i].PN)
                  formatString += "<br /><strong><i>CFDA Program Number:</i></strong> " + recipientInfos[i].PN;

              if (recipientInfos[i].MAN)
                  formatString += "<br /><strong><i>Department:</i></strong> " + recipientInfos[i].MAN;

              if (recipientInfos[i].AN)
                  formatString += "<br /><strong><i>Funding Agency:</i></strong> " + recipientInfos[i].AN;

              if (recipientInfos[i].FAI)
                  formatString += "<br /><strong><i>Award Number:</i></strong> " + recipientInfos[0].FAI;

              if (recipientInfos[i].N)
                  formatString += "<br /><strong><i>Recipient:</i></strong> " + recipientInfos[i].N;

              if (recipientInfos[i].A)
                  formatString += "<br /><strong><i>Recipient Address:</i></strong> <br />" + recipientInfos[i].A;

              //check if this primary award recipient has sub-awards.
              if (recipientInfos[i].HS > 0)
                  formatString += "<br /><i>Show <a href=\"javascript:mmc.findSubAwardees('" + recipientInfos[i].FAI + "')\">sub-award recipients</a> in this state.</i> <br />";

          }
          else if (recipientInfos[i].RT == 2) {

              if (recipientInfos[i].T)
                  formatString += "<br /><strong>" + recipientInfos[i].T + "</strong>";

              if (recipientInfos[i].PD)
                  formatString += "<br /><strong><i>Description:</i></strong> " + recipientInfos[i].PD;

              if (recipientInfos[i].PN)
                  formatString += "<br /><strong><i>CFDA Program Number:</i></strong> " + recipientInfos[i].PN;

              if (recipientInfos[i].MAN)
                  formatString += "<br /><strong><i>Department:</i></strong> " + recipientInfos[i].MAN;

              if (recipientInfos[i].AN)
                  formatString += "<br /><strong><i>Funding Agency:</i></strong> " + recipientInfos[i].AN;

              if (recipientInfos[i].FAI)
                  formatString += "<br /><strong><i>Sub-Award Number:</i></strong> " + recipientInfos[i].FAI;

              if (recipientInfos[i].N)
                  formatString += "<br /><strong><i>Sub-Award Grantee:</i></strong> " + recipientInfos[i].N;

              if (recipientInfos[i].A)
                  formatString += "<br /><strong><i>Sub-Award Grantee Address:</i></strong> <br />" + recipientInfos[i].A;
          }
          else {

              if (recipientInfos[i].N)
                  formatString += "<strong>" + recipientInfos[i].N + "</strong>";

              if (recipientInfos[i].PD)
                  formatString += "<br /><strong><i>Description:</i></strong> " + recipientInfos[i].PD;

              if (recipientInfos[i].PN)
                  formatString += "<br /><strong><i>CFDA Program Number:</i></strong> " + recipientInfos[i].PN;

              if (recipientInfos[i].MAN)
                  formatString += "<br /><strong><i>Department:</i></strong> " + recipientInfos[i].MAN;

              if (recipientInfos[i].AN)
                  formatString += "<br /><strong><i>Funding Agency:</i></strong> " + recipientInfos[i].AN;

              if (recipientInfos[i].FAI)
                  formatString += "<br /><strong><i>Award Number:</i></strong> " + recipientInfos[0].FAI;

              if (recipientInfos[i].N)
                  formatString += "<br /><strong><i>Recipient:</i></strong> " + recipientInfos[i].N;

              if (recipientInfos[i].A)
                  formatString += "<br /><strong><i>Recipient Address:</i></strong> <br />" + recipientInfos[i].A;
          }

          formatString += "</p>";
      }

      return formatString;
  }

  function findPrograms(e) {
      clearInfo();

      var address = (jQuery("#address").val() == 'Address or Zipcode (required)') ? '' : jQuery("#address").val();
      var keyword = (jQuery("#keyword").val() == 'Keywords') ? '': jQuery("#keyword").val();

      //Check if an address and keywork is specified.
      //if ((address.trim().length == 0 && keyword.trim().length == 0))
      //{
      //    unblockMain();

      //    updateInfo("An Address, Keyword or both is required.");

      //    e.preventDefault();

      //    return false;
      //}

      blockMain();

      jQuery.ajax({
          url: 'mmc/api/ResolveAddress',
          data: {
              Address: address,
              Radius: jQuery("#radius :selected").val(),
              Keyword: keyword,
              TopicFilters: getTopicFilters(),
              DepartmentFilters: getDepartmentFilters()
          },
          dataType: 'json',
          success: function (model) {
              if (model.StatusCode == 602 || model.StatusCode == 601) {
                  unblockMain();
                  updateInfo("Unable to locate the address provided.");
                  clearOverlays();
                  clearRecipients();
              }
              else {
                  jQuery.ajax({
                      url: '/mmc/api/FindPrograms',
                      data: model,
                      dataType: 'json',
                      success: markMapCoordinates,
                      error: function (jqXHR, textStatus, errorThrown) {
                          unblockMain();
                      }
                  });
                  query.latitude = model.Latitude;
                  query.longitude = model.Longitude;
                  query.zipcode = model.ZipCode;
                  query.radius = model.Radius;
                  query.keywords = model.Keyword;

                  jQuery.ajax({
                    url: 'mmc/api/FindProgramRecipientInfos',
                    data: model,
                    jsonp: 'callback',
                    dataType: 'json',
                    success: listRecipients,
                    error: function (jqXHR, textStatus, errorThrown) {
                        unblockMain();
                    }
                });
              }
          },
          error: function (jqXHR, textStatus, errorThrown) {
              unblockMain();
          }
      });

      return false;
  }

  w.mmc = {
      init: function () {
          var postedAddress = jQuery("#postedAddress");
          var postedRadius = jQuery("#postedRadius");
          var postedTopicFilters = jQuery("#postedTopicFilters");
          var postedDepartmentFilters = jQuery("#postedDepartmentFilters");
          var postedKeyword = jQuery("#postedKeyword");
          var textBoxAddress = jQuery("#address");
          var textBoxKeyword = jQuery("#keyword");
          var mapOptions = {
              zoom: 4,
              center: { lat: 40.00000, lng: -98.00000 },
              mapTypeId: google.maps.MapTypeId.ROADMAP
          };

          map = new google.maps.Map(jQuery("#mapCanvas")[0], mapOptions);

          textBoxAddress.keypress(function (e) {
              var keyCode = e.which ? e.which : e.keyCode;

              if (keyCode == 13) {
                  jQuery(this).blur();
                  jQuery("#findPrograms").focus().click();
                  e.preventDefault();
              }
          });

          textBoxKeyword.keypress(function (e) {
              var keyCode = e.which ? e.which : e.keyCode;

              if (keyCode == 13) {
                  jQuery("#keyword").blur();
                  jQuery("#findPrograms").focus().click();
                  e.preventDefault();
              }
          });

          jQuery("#findPrograms").on('click', findPrograms);

          jQuery("#printPrograms").on('click', function () {

              jQuery.blockUI({
                  message: jQuery('#printQuestion'),
                  css: {
                      width: '450px',
                      '-moz-opacity': '1',
                      opacity: '1',
                      left: '30%'
                  },
                  overlayCSS: { opacity: 0.5 }
              });
          });

          if (postedAddress.val().length > 0 || postedKeyword.val().length > 0) {
              jQuery("#address").val(postedAddress.val());
              jQuery("#radius").val(postedRadius.val());
              jQuery("#keyword").val(postedKeyword.val());

              jQuery(".topicFilter").each(function () { jQuery(this).attr('checked', false) });
              var topicIds = postedTopicFilters.val().split(",");
              jQuery(topicIds).each(function (index, topicId) {
                  jQuery('.topicFilter[value="' + topicId + '"]').attr('checked', true);
              });

              jQuery(".departmentFilter").each(function () { jQuery(this).attr('checked', false) });
              var departmentIds = postedDepartmentFilters.val().split(",");
              jQuery(departmentIds).each(function (index, departmentId) {
                  jQuery('.departmentFilter[value="' + departmentId + '"]').attr('checked', true);
              });

              jQuery("#findPrograms").focus().click();
          }
      },
      findSubAwardees: function (fai) {
          clearInfo();

          jQuery.ajax({
              url: url + "/Maps/GetSubAwardees",
              data: { FederalAwardId: fai },
              jsonp: 'callback',
              dataType: 'jsonp',
              success: markMapCoordinates,
              error: function (jqXHR, textStatus, errorThrown) {
                  unblockMain();
              }
          });
      },
      findPrimeAwardee: function (fai) {
          clearInfo();

          jQuery.ajax({
              url: url + "/Maps/GetPrimeAwardees",
              data: { FederalAwardId: fai },
              jsonp: 'callback',
              dataType: 'jsonp',
              success: markMapCoordinates,
              error: function (jqXHR, textStatus, errorThrown) {
                  unblockMain();
              }
          });
      }
  };

}(window);

// window.mmc.init();

// This function doesn't appear to trigger via the callback.
// ?apikey&callback=initMmc
function initMmc() {
  console.log('initMmc triggered');
  window.mmc.init();
}