jQuery(function($) {

  /* General functions */
  initClickable();
  initDatepickerEvent();
  initExternalLinks();
  initItemRemoveConfirmation();
  initSearch();
  
  /* Members area */
  initConditionalFields();
  initDatepickerProfil();
  initMaxLengthHandler();
  initRepeatPassword();
  initSubmissionForm();
  initURLinput();
  
  /* Arztfinder */
  initGeolocationSearch();
  initGeolocationVerification();
  initFinderTabs();
});


/**
 * This function makes blocks containing a link clickable. 
 */ 
function initClickable()
{
  if (! $('.clickable').length ) return;
  
  $('.clickable')
  .hover(
    function()
    {
      $(this).addClass('clickableHover');
    },
    
    function()
    {
      $(this).removeClass('clickableHover');
    }
  )
  .click(function()
  {
    var newlocation = $('a', this).attr('href');
    if (newlocation.length === 0)
    {
      return false;
    }
    window.location = newlocation;
  });
}


/**
 * This function adds a datepicker to the given date input fields 
 */ 
function initDatepickerEvent()
{
  if (! $('#eventform #exp_date').length ) return;
  
  $("#eventform #exp_date").datepicker({
    changeYear: true,
    changeMonth: true,
    dateFormat: 'd.m.yy',
    dayNames: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
    dayNamesMin: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
    firstDay: 1,
    monthNames: ['Jänner','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'],
    monthNamesShort: ['Jan','Feb','Mar','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'],
    yearRange: '2010:2020'
  });
}


/* Force links with rel="extern" to open in a new window */
function initExternalLinks ()
{
  $('a[rel="extern"]').removeAttr('rel').attr('target', '_blank');
  $('a.relextern').removeClass('relextern').attr('target', '_blank');
}


/**
 * Display confirm alert when an item is about to be removed
 **/ 
function initItemRemoveConfirmation ()
{
  if ( $('.removeItem').length === 0 ) return;
  
  $('.removeItem').click(function()
  {
    return confirm("Wollen Sie diesen Eintrag wirklich löschen?");
  });
}


/**
 * This function takes care of the String replacement in the search field.
 */ 
function initSearch()
{
  if (! $('#searchterm').length ) return;
  
  var searchterm = 'Suchbegriff';
  $('#searchterm').val(searchterm);
  $('#searchterm').focus(function()
  {
    if( $(this).val() == searchterm ) $(this).val('');
  });
  $('#searchterm').blur(function()
  {
    if( $(this).val() === '' ) $(this).val(searchterm);
  });
}


/* MEMBERS AREA */

/**
 * This function hides and reveals the conditional input fields 
 */ 
function initConditionalFields()
{
  if (! $('#mitgliedsdaten, #submissionform').length ) return;
  
  /* hide all divs that have the class "inactive", apart from the ones
    where the checkbox is checked */
  $(".changer").each(function()
  {
    if (!$(this).attr("checked"))
    {
      $(this).parent().next(".inactive").hide();
      
      /* IE7 fix: Elements with position:relative containing elements with
                  position:absolute are not updated */
      if ($.browser.msie && jQuery.browser.version < 7.0)
      {
        $("div.option, div.combined, div.input, #verpflichtungserklaerung").hide().show();
      }
    }
  });
  
  /* add onlick handlers to the inputfields with class "changer" */
  $(".changer").click(function()
  {
    /* disable all options with the same name */
    inputName = $(this).attr("name");
    $('input[name="'+inputName+'"]').parent().next(".inactive").hide();
    
    if ($(this).attr("checked"))
    {
      $(this).parent().next(".inactive").show();
    }
    
    /* IE7 fix: Elements with position:relative containing elements with
                position:absolute are not updated */
    if ($.browser.msie)
    {
      $("div.option, div.combined, div.input").hide().show();
    }
  });
  
  
  /* Only relevant for Mitgliedsdaten form */
  if (! $('#mitgliedsdaten').length ) return;
  
  /* Disclosure of conditional fields for secondary address */
  if (  $("#Mitgliedsstatus").val() == "Pension" ||
        $("#Mitgliedsstatus").val() == "Ehrenmitglied" )
  {
    $('#secondary_address').hide();
  }
  /* If retired or honorary member, hide secondary address */
  $("#Mitgliedsstatus").change(function() {
    if ( $(this).val() == "Pension" || $(this).val() == "Ehrenmitglied")
    {
      $('#secondary_address').hide();
    }
    else
    {
      $('#secondary_address').show();
    }
  });
  
  /* Disclosure of conditional address field "Zustelladresse_Bezeichnung"*/
  if (  $("#Zustelladresse_Art").val() === "" ||
        $("#Zustelladresse_Art").val() == "Privat" )
  {
    $('#Zustelladresse_Bezeichnung').parent().hide();
  }
  $("#Zustelladresse_Art").change(function() {
    if ( $(this).val() === "" || $(this).val() == "Privat")
    {
      $('#Zustelladresse_Bezeichnung').parent().hide();
    }
    else
    {
      $('#Zustelladresse_Bezeichnung').parent().show();
    }
  });
  
  /* Disclosure of conditional address field "Zweitadresse_Bezeichnung"*/
  if (  $("#Zweitadresse_Art").val() === "" ||
        $("#Zweitadresse_Art").val() == "Privat" )
  {
    $('#Zweitadresse_Bezeichnung').parent().hide();
  }
  $("#Zweitadresse_Art").change(function() {
    if ( $(this).val() === "" || $(this).val() == "Privat")
    {
      $('#Zweitadresse_Bezeichnung').parent().hide();
    }
    else
    {
      $('#Zweitadresse_Bezeichnung').parent().show();
    }
  });
}


/**
 * This function adds a datepicker to the given date input fields 
 */ 
function initDatepickerProfil()
{
  if (! $('#Geburtsdatum').length ) return;
  
  $("#Geburtsdatum").datepicker({
    changeYear: true,
    changeMonth: true,
    dateFormat: 'd.m.yy',
    dayNames: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
    dayNamesMin: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
    firstDay: 1,
    monthNames: ['Jänner','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'],
    monthNamesShort: ['Jan','Feb','Mar','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'],
    yearRange: '1900:2010'
  });
}


/**
 * Limit the number of characters in the input fields
 * */ 
function initMaxLengthHandler ()
{
  /* Insert HTML-Markup */
  $('textarea[maxlength]').each(function(){
    $(this).parent().append('<p class="chars_available"></p>');
    //var max = parseInt($(this).attr('maxlength'));
    //var contentlength = $(this).val().length;
    updateTextareaCharsRemaining($(this))
  });
  
  /* Zeichenbegrenzung & Anzeige der Restzeichen. */
  $('textarea[maxlength]').keyup(function() {
    updateTextareaCharsRemaining($(this))
  });
  
  function updateTextareaCharsRemaining (textarea)
  {
    var max = parseInt(textarea.attr('maxlength'));
    var contentlength = textarea.val().length;
    var message = "";
    
    if( contentlength > max )
    {
      /* Truncate the content if necessarry */
      //textarea.val(textarea.val().substr(0, max));
    }
    
    var charsremaining = max - contentlength;
    if (charsremaining < 0)
    {
      charsremaining = Math.abs(charsremaining);
      message = charsremaining + " Zeichen zu viel";
    }
    else
    {
      message = "noch " + charsremaining + " Zeichen";
    }
    
    /* Update the number remaining chars */
    textarea.parent().find('.chars_available').html(message);
  }
}


/**
 * This function reveals the password repeat field on password change 
 */ 
function initRepeatPassword()
{
  /* Skip if there is no password field or if there was an error for the confirmation field */
  if (! $('#newPassword2').length ||
      $('div.error #newPassword2').length) return;
  
  $("#newPassword2").parent().hide();
  
  $("#newPassword1").change(function() {
    if ($(this).val().length > 0)
    {
      $("#newPassword2").parent().show();
      $("#newPassword2").focus();
    }
    else
    {
      $("#newPassword2").parent().hide();
    }
  });
}


/* JS optimization for the submission form */
function initSubmissionForm ()
{
  if (! $('#submissionform').length) return;
  
  /* Loop through coauthors and hide inactive fieldsets */
  $('fieldset.coautor').each(function() {
    if ($(this).show().find('input.toggle').val() === "")
    {
      $(this).hide();
    }
  });
  
  /* Insert remove-button */
  $('#coautor_controls').append('<p><a href="#" id="remove_coautor">Co-Autor entfernen</a></p>').find('#remove_coautor').hide();
  if ($('fieldset.coautor:visible').length > 0)
  {
    $('#remove_coautor').show();
  }
  
  /* Insert add-button */
  $('#coautor_controls').append('<p><a href="#" id="add_coautor">Co-Autor einfügen</a></p>').find('#add_coautor').hide();
  if ($('fieldset.coautor:visible').length < 6)
  {
    $('#add_coautor').show();
  }
  
  /* IE7 fix: Elements with position:relative containing elements with
              position:absolute are not updated */
  if ($.browser.msie)
  {
    $("div.option, div.combined, div.input").hide().show();
  }
  
  /* Add-button listener */
  $('#add_coautor').click(function(){
    $('fieldset.coautor:hidden:first').slideDown("300",function()
    {
      // Animation complete.
      if ($('fieldset.coautor:visible').length > 5)
      {
        $('#add_coautor').hide();
      }
      
      /* IE7 fix: Elements with position:relative containing elements with
                  position:absolute are not updated */
      if ($.browser.msie)
      {
        $("div.option, div.combined, div.input").hide().show();
      }
    })
    .find('input.toggle').val('true');
    
    $('#remove_coautor').show();
    
    return false;
  });
  
  
  /* Remove-button listener */
  $('#remove_coautor').click(function(){
    $('fieldset.coautor:visible:last').slideUp("300",function()
    {
      // Animation complete.
      if ($('fieldset.coautor:visible').length === 0)
      {
        $('#remove_coautor').hide();
      }
      
      /* IE7 fix: Elements with position:relative containing elements with
                  position:absolute are not updated */
      if ($.browser.msie)
      {
        $("div.option, div.combined, div.input").hide().show();
      }
    })
    .find('input.toggle').val('');
    
    $('#add_coautor').show();
    
    return false;
  });
}

/**
 * This function adds the text "http://" to empty URL fields and removes the text onSubmit.
 */ 
function initURLinput()
{
  if (! $('.url').length ) return;
  
  $('.url').each(function()
  {
    if ($(this).val() == "")
    {
      $(this).val("http://")
    }
  });
  
  $('.url').parents("form").submit(function()
  {
    $(this).find('.url').each(function()
    {
      if ($(this).val() == "http://")
      {
        $(this).val("")
      }
    });
  });
}


/* ARZTFINDER */

/**********************/
/* Geolocation Search */
/**********************/

function initGeolocationSearch()
{
  if ( $('#finderForm').length === 0 ) return;
  
  /* DOM Elements we need more often */
  var state = $('#state'),
      form = $('#finderForm'),
      searchPositionLat = $('#adresse_lat'),
      searchPositionLng = $('#adresse_long'),
      searchName = $('#searchName'),
      searchAddress = $('#searchAddress'),
      searchOptions = $('#searchOptions'),
      searchOptionsToggle = $('#searchOptionsToggle a'),
      addressVerification = $('#addressVerification'),
      mapElement = addressVerification.append('<div id="map" class="dontShow" style="width: 100%; height: 400px"></div>').children('#map'),
      mapToggle = addressVerification.prepend('<a id="mapToggle" href="#">Karte anzeigen</a>').children('#mapToggle').hide()
  
  /* all map variables */
  var mapOptions = {
        center: new google.maps.LatLng(47.353711, 13.458252),
        zoom: 13,
        mapTypeControl: true,
        mapTypeControlOptions: {
          style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
        },
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        scrollwheel: false
      },
      geocoder = new google.maps.Geocoder(),
      locationMarker,
      markerArray = new Array(),
      map;
      mapIcons = ['red_MarkerA.png','red_MarkerB.png','red_MarkerC.png','red_MarkerD.png','red_MarkerE.png','red_MarkerF.png','red_MarkerG.png','red_MarkerH.png','red_MarkerI.png','red_MarkerJ.png','red_MarkerK.png','red_MarkerL.png','red_MarkerM.png','red_MarkerN.png','red_MarkerO.png','red_MarkerP.png','red_MarkerQ.png','red_MarkerR.png','red_MarkerS.png','red_MarkerT.png','red_MarkerU.png','red_MarkerV.png','red_MarkerW.png','red_MarkerX.png','red_MarkerY.png','red_MarkerZ.png'];
  
  /* all status variables */
  var initMapFinished = false,
      initFormsFinished = false,
      geoLocatingAllowed = false,
      /* Status variable, so the geocoder callback can force a submit */
      forceSubmit = false,
      submitButtonPressed = false,
      alreadySearched = $('#searched').val(),
      /* Status variable, to suppress geocoding if the location was determined by the browser */
      doGeoCode = false;
  
  /* Boundaries for Austria */
  var allowedBounds = new google.maps.LatLngBounds(
    new google.maps.LatLng(46.37, 9.53),
    new google.maps.LatLng(49.02, 17.16));
  
  // ************* 
  // Prepare HTML 
  // ************* 
  
  
  // ***************** 
  // Prepare Listeners 
  // ***************** 
  
  /* Update map */
  $('#mapUpdate').click(function()
  {
    /* Return if no address or position given */
    if (  searchAddress.val() == '' &&
          searchPositionLat.val().length === 0 &&
          searchPositionLng.val().length === 0)
    {
      enterAddressAgain();
      return false;
    }
    
    /* Reset the submit button status variable, so the map is updated */
    submitButtonPressed = false;
    
    addressSearch();
    mapToggle.html("Karte ausblenden").show();
    return false;
  });
  
  /* Map toggle */
  mapToggle.click(function()
  {
    if (mapElement.is(':visible'))
    {
      mapElement.slideUp(300);
      mapToggle.html("Karte anzeigen").hide();
    }
    else
    {
      addressSearch();
      mapToggle.html("Karte ausblenden").show();
    }
    return false;
  });
  
  /* GeoCode on searchAddress updates */
  searchAddress.change(function()
  {
    doGeoCode = true;
  });
  
  /* Options Toggle */
  searchOptionsToggle.click(function()
  {
    if (searchOptions.is(':visible'))
    {
      searchOptions.slideUp(300);
      searchOptionsToggle.html("einblenden");
    }
    else
    {
      searchOptions.slideDown(300);
      searchOptionsToggle.html("ausblenden");
    }
    return false;
  });
  
  
  // ************** 
  // Initialize Map
  // ************** 
  
  /* Initialize map if results are available */
  if ($('#results').length !== 0)
  {
    addressSearch();
    mapToggle.html("Karte ausblenden").show();
  }
  
  /* If no address given, try to retrieve the location from the browser */
  if( searchAddress.val() == '' &&
      searchPositionLat.val().length === 0 &&
      searchPositionLng.val().length === 0 &&
      navigator.geolocation )
  {
    navigator.geolocation.getCurrentPosition(function(position)
    {
        geoLocatingAllowed = true;
        mapElement.slideDown(300, function() {
          initMap(new google.maps.LatLng(position.coords.latitude, position.coords.longitude));
          mapToggle.html("Karte ausblenden").show();
        });
    });
  }
  
  function initMap (position)
  {
    map = new google.maps.Map(mapElement.get(0), mapOptions);
    locationMarker = new google.maps.Marker({
      position: mapOptions.center,
      title: 'Ihr Standort',
      map: map
    });
    locationMarker.setVisible(false);
    markerArray.push(locationMarker);
    
    /* If we have a location already, set the marker */
    if (  alreadySearched == '1' &&
          searchPositionLat.val().length !== 0 &&
          searchPositionLng.val().length !== 0)
    {
      position = new google.maps.LatLng(searchPositionLat.val(), searchPositionLng.val());
    }
    
    /* Set position if available or if geoLocating is activated */
    if (  (geoLocatingAllowed && position) ||
          (alreadySearched == '1' && position) )
    {
      map.setCenter(position);
      locationMarker.setPosition(map.getCenter());
      locationMarker.setVisible(true);
      searchPositionLat.val(map.getCenter().lat());
      searchPositionLng.val(map.getCenter().lng());
    }
    
    /* Update the location data on user interaction (click) */
    google.maps.event.addListener(map, 'click', function(e)
    {
      /* Return if in results view */
      if ($('#results').length !== 0) return false;
      
      /* Return if not address given */
      if ( searchAddress.val() == '' )
      {
        /* Try to retrieve the location from the browser */
        if ( navigator.geolocation )
        {
          navigator.geolocation.getCurrentPosition(function(position)
          {
              geoLocatingAllowed = true;
              mapElement.slideDown(300, function() {
                initMap(new google.maps.LatLng(position.coords.latitude, position.coords.longitude));
              });
          });
        }
        enterAddressAgain();
        return false;
      }
      
      setTimeout(function(){
        locationMarker.setPosition(e.latLng);
        locationMarker.setVisible(true);
      }, 300);
      searchPositionLat.val(e.latLng.lat());
      searchPositionLng.val(e.latLng.lng());
      doGeoCode = false;
      return false;
    });
    
    /* Listen for the dragend event and override default behaviour */
    google.maps.event.addListener(map, 'dragend', function()
    {
      /* Return if map is within bounds */
      if (allowedBounds.contains(map.getCenter())) return;
      
      /* Out of bounds - Move the map back within the bounds */
      var c = map.getCenter(),
          x = c.lng(),
          y = c.lat(),
          maxX = allowedBounds.getNorthEast().lng(),
          maxY = allowedBounds.getNorthEast().lat(),
          minX = allowedBounds.getSouthWest().lng(),
          minY = allowedBounds.getSouthWest().lat();
      
      if (x < minX) x = minX;
      if (x > maxX) x = maxX;
      if (y < minY) y = minY;
      if (y > maxY) y = maxY;
      
      map.setCenter(new google.maps.LatLng(y, x));
    });
    
    /* Listen for zoom events to limit zoom level */
    google.maps.event.addListener(map, 'zoom_changed', function()
    {
      if (map.getZoom() < 6)
      {
        map.setZoom(6);
      }
    });
    
    /* Process search results and populate markers */
    infoWindow = new google.maps.InfoWindow();
    $('#results .vcard').each(function(index)
    {
      /* create our icons */
      var address = $('.street-address', this).html() + ', ';
      address += $('.postal-code', this).html() + ', ';
      address += $('.locality', this).html() + ', ';
      address += $('.region', this).html() + ' ';
      name = $('.fn', this).html();
      var html = "<strong>" + name + "</strong><br />";
      html += $('.adr .street-address', this).html() + "<br />";
      html += $('.adr .postal-code', this).html() + " " + $('.adr .locality', this).html() + "<br />";
      html += $('.url', this).html();
      var geo_longitude = $('.longitude', this).html();
      var geo_latitude = $('.latitude', this).html();
      var geo_location = new google.maps.LatLng(geo_latitude, geo_longitude);
      
      var nameIndex = index + 1; // offset
      var marker = new google.maps.Marker({
        map: map,
        position: geo_location,
        icon: '/images/ui/maps/'+mapIcons[index],
        title: nameIndex+': ' + name
      });
      markerArray.push(marker);
      
      /* bind event listener to marker on map */
      google.maps.event.addListener(marker, 'click', function()
      {
        infoWindow.setContent(html);
        infoWindow.open(map,marker);
      });
      
      /* bind event listener to marker in results-list */
      $('#results .vcard:eq('+index+') .datum').bind("click", function ()
      {
        $('html, body').animate({ scrollTop: $("#finderForm").offset().top }, 500);
        infoWindow.setContent(html);
        infoWindow.open(map,marker);
        
        if (!mapElement.is(':visible'))
        {
          mapElement.slideDown(300);
          mapToggle.html("Karte ausblenden").show();
        }
        return false;
      });
    });
    autozoom();
    initMapFinished = true;
  }
  
  /**
    * Decode the address.
    * @returns false, since we have to handle geocoding results in the callback function of geoCode(). 
    * */
  function addressSearch( dontShowMap )
  {
    addressValue = searchAddress.val();
    
    /* Don't update/show the map if ready to submit */
    if ( dontShowMap === true )
    {
      if (! initMapFinished )
      {
        initMap();
      }
      geoCode();
    }
    else
    /* Initialise and show the map */
    if ( initMapFinished === false )
    {
      mapElement.slideDown(300, function() {
        initMap();
        geoCode();
      });
    }
    /* Just show the map */
    else if ( mapElement.hasClass('dontShow') )
    {
      mapElement.slideDown(300, function() {
        geoCode();
      });
    }
    /* geoCode only */
    else
    {
      geoCode();
    }
    return false;
  }
  
  /** 
    * Decode the address
    * @returns false, since we have to handle geocoding results in the callback function. 
    * */
  function geoCode ()
  {
    /* check if address is set, return if not */
    if ( addressValue.length === 0 )
    {
      return false;
    }
    
    if ( doGeoCode === false )
    {
      /* Just update the map */
      map.setCenter(new google.maps.LatLng(searchPositionLat.val(), searchPositionLng.val()));
      locationMarker.setPosition(map.getCenter());
      locationMarker.setVisible(true);
      return false;
    }
    
    /* call geocoder with callback function */
    geocoder.geocode( { 'address': addressValue, 'region': 'AT' }, function(results, status) {
      if ( status == google.maps.GeocoderStatus.OK )
      /* on Success */
      {
        /* Only set/overwrite Lat/Lng if we have to */
        if ( doGeoCode === true )
        {
          searchPositionLat.val(results[0].geometry.location.lat());
          searchPositionLng.val(results[0].geometry.location.lng());
        }
        
        /* If we are submitting, we don't have to update the map */
        if ( submitButtonPressed === true )
        {
          doGeoCode = false;
          forceSubmit = true;
          
          /* force resubmit */
          form.submit();
          return false;
        }
        
        /* Update the map */
        map.setCenter(new google.maps.LatLng(searchPositionLat.val(), searchPositionLng.val()));
        locationMarker.setPosition(map.getCenter());
        locationMarker.setVisible(true);
        autozoom();
      }
      else if ( status == google.maps.GeocoderStatus.UNKNOWN_ERROR )
      {
        setTimeout(geoCode, 500);
      }
      else if ( status == google.maps.GeocoderStatus.ZERO_RESULTS ||
                status == google.maps.GeocoderStatus.INVALID_REQUEST)
      {
        enterAddressAgain();
        submitButtonPressed = false;
      }
      return false;
    });
    return false;
  }
  
  /* Form submit handler */
  form.submit(function()
  {
    /* Don't check geocoding in name search */
    if ( $('#filterName').attr("checked") )
    {
      return true;
    }
    
    /* can we send the form instantly */
    if  ( forceSubmit === true ||
          (
            doGeoCode === false &&
            searchPositionLat.val().length !== 0 &&
            searchPositionLng.val().length !== 0
          )
          // || searchName.val().length !== 0
        )
    {
      return true;
    }
    
    /* Set submission mode */
    submitButtonPressed = true;
    
    if ( searchAddress.val() == '' )
    {
      enterAddressAgain();
    }
    else
    {
      addressSearch(true);
    }
    
    return false;
  });
  
  /* Try to adjust the zoom level automatically */
  function autozoom()
  {
    /* set center and default zoom level */
    map.setCenter(locationMarker.getPosition());
    map.setZoom(15);
    
    /* if search results, adjust zoom level (autofit) */
    if ( $('#results').length !== 0 )
    {
      setTimeout(function() {
        var bounds = map.getBounds();
        for (var i = 0; i < markerArray.length; ++i)
        {
          if (! bounds.contains(markerArray[i].position))
          {
            bounds = bounds.extend(markerArray[i].position);
          }
        }
        map.fitBounds(bounds);
      }, 300);
    }
  }
  
  /* Focus to the Address Field and give a hint */
  function enterAddressAgain ()
  {
    /* ### Hinweis für User geben */
    searchAddress.focus();
  }
}


/***************************************/
/* Address Verification when logged in */
/***************************************/
function initGeolocationVerification ()
{
  if (! $('#finderdaten').length) return;
  
  /* DOM Elements we need more often */
  var addressVerification = $('#addressVerification'),
      typeField = $('#adresse_art').val(),
      streetField = $('#adresse_anschrift'),
      zipField = $('#adresse_plz'),
      cityField = $('#adresse_ort'),
      addressField = $('#address'),
      addressValue,
      addressVerifiedField = $('#adresse_bestaetigt'),
      searchPositionLat = $('#adresse_lat'),
      searchPositionLng = $('#adresse_long'),
      form = $('#finderdaten'),
      infoElement,
      addressVerifier,
      saveAddress,
      mapResetPosition,
      mapUpdater,
      mapElement = addressVerification.append('<div id="map" style="width: 100%; height: 400px"></div>').children('#map');
  
  /* Variables */
  var mapOptions =
      {
        center: new google.maps.LatLng(47.353711, 13.458252),
        zoom: 6,
        mapTypeControl: true,
        mapTypeControlOptions:
        {
          style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
        },
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        scrollwheel: false
      },
      map,
      marker,
      geocoder = new google.maps.Geocoder();
  
  /* HTML Changes beforehand */
  if ( typeField == "o")
  {
    mapResetPosition = addressField.after('<p><a id="updateMap" href="#">Position zurücksetzen</a></p>').next('p').children('#updateMap');
  }
  else{
    mapUpdater = cityField.after('<p><a id="updateMap" href="#">Karte aktualisieren</a></p>').next('p').children('#updateMap');
  }
  
  addressVerification.prepend('<p id="info" class="notice">Position nicht bestätigt.</p><a id="verifyAddress" href="#">Position bestätigen</a><a id="saveAddress" href="#">Speichern</a><p class="small">Der rote Marker zeigt die Position Ihrer Ordination. Sie können durch Klicken die Position des Markers ändern.</p>');
  addressVerifier = $('#verifyAddress');
  saveAddress = $('#saveAddress').hide();
  infoElement = $('#info');
  
  /* Change Info if Position verified */
  if ( addressVerifiedField.val() == 1 )
  {
    toggleInfo(true, true);
  }
  
  addressVerifier.click(verifyAddress);
  saveAddress.click(function() { form.submit(); return false; });
  if ( typeField == "o")
  {
    mapResetPosition.click(updateMap);
  }
  else
  {
    mapUpdater.click(updateMap);
    $('#adresse_anschrift, #adresse_plz, #adresse_ort').change(function() {
      toggleInfo(false);
    });
  }  
  
  initMap();
  
  function toggleInfo (state, initialyVerified)
  {
    var verified = infoElement.hasClass('info') ? 1 : 0;
    
    /* Exit if verified value already up-to-date */
    if ( (state === false && verified === 0) || (state === true && verified === 1) ) return;
    
    var text =  infoElement.text() == 'Position bestätigt.' ? 'Position nicht bestätigt.' : 'Position bestätigt.';
    infoElement
      .toggleClass('notice')
      .toggleClass('info')
      .text(text);
    
    /* Add event handler */ 
    addressVerifier.toggle();
    addressVerifiedField.val(Math.abs(verified-1));
    
    if ( initialyVerified )
    {
      if ( typeField == "o" )
      {
        mapResetPosition.hide();
      }
      return;
    }
    
    if ( state === true )
    {
      saveAddress.show();
    }
    else if ( state === false )
    {
      saveAddress.hide();
    }
    else
    {
      saveAddress.toggle();
    }
  }
  
  function verifyAddress ()
  {
    toggleInfo(true);
    map.setCenter(marker.getPosition());
    return false;
  }
  
  function initMap ()
  {
    map = new google.maps.Map(mapElement.get(0), mapOptions);
    marker = new google.maps.Marker(
    {
      position: mapOptions.center,
      title: 'Ihr Standort',
      map: map
    });
    
    google.maps.event.addListener(map, 'click', function(e)
    {
      setTimeout( function() {
                    marker.setPosition(e.latLng)
                  },
                  300);
      searchPositionLat.val(e.latLng.lat());
      searchPositionLng.val(e.latLng.lng());
      toggleInfo(false);
      if ( typeField == "o")
      {
        mapResetPosition.show();
      }
    });
    
    /* if the Address is already verified set it to the verified positions
       else geoCode the information in the Address fields */
    if ( addressVerifiedField.val() == 1 )
    {
      map.setCenter(new google.maps.LatLng(searchPositionLat.val(), searchPositionLng.val()));
      map.setZoom(15);
      marker.setPosition(map.getCenter());
    }
    else
    {
      geoCode(getCurrentAddress());
    }
  }
  
  function getCurrentAddress()
  {
    return streetField.val() + ', ' + zipField.val() + ' ' + cityField.val();
  }
  
  function updateMap ()
  {
    geoCode(getCurrentAddress());
    toggleInfo(false);
    if ( typeField == "o")
    {
      mapResetPosition.hide();
    }
    
    return false;
  }
  
  function geoCode (address)
  {
    geocoder.geocode( { 'address': address, 'region': 'AT' }, function(results, status) {
      if (status == google.maps.GeocoderStatus.OK)
      {
        map.setCenter(results[0].geometry.location);
        map.setZoom(15);
        setTimeout( function() {
                      marker.setPosition(results[0].geometry.location);
                    }, 300);
        searchPositionLat.val(map.getCenter().lat());
        searchPositionLng.val(map.getCenter().lng());
      }
    });
  }
}


/**
  * Manipulate the reference search form. 
  */ 
function initFinderTabs()
{
  if (! $('#finderForm').length ) return;
  
  /**
   * Change the selected filter. Available filters are:
   * filterName, filterStandort
   * */
  $('#filterMenu label')
  .click(function()
  {
    /* Hide all select fields */
    $('#Name, #Standort')
    .removeClass('active')
    .addClass('none');
    
    /* Activate the select for the clicked filter */
    selectName = $(this).prev('input[type=radio]').attr("id").replace("filter","");
    $('#'+selectName).removeClass('none');
    $('#'+selectName).addClass('active');
    
    /* Hide the map */
    $('#map, #mapToggle').hide();
    
    /* Update the menu */
    $('#filterMenu li').removeClass('active');
    $(this).parent('li').addClass('active').find('input').attr('checked', true);;
  });
}

