/**
 * GX Webmanager Utility for Cendris AddressX - WMCendrisAX
 * 
 * @version 2.0.1
 * @author Taco Stuivenberg, Paul Speijers, David Kessler
 * 
 * Depends on jQuery
 * 
 * The cendrisService searches for address information, and gets the city,
 * street and netnumber (the resultfields), based on the zipcode and housenumber
 * (the search fields). It will hide or show the error field, based on whether
 * search results were found.
 * 
 * Both the search and the result fields need to be provided by using the
 * subscribeWithCendris method. For example: When you call
 * subscribeWithCendris('zipcode', 'myZipcodeFieldId') you tell the
 * cendrisService that your HTML dom element with id 'myZipcodeFieldId' is the
 * zipcode field. This way, the cendrisService can get the zipcode DOM element
 * using the id and it will use it as the zipcode searchfield when searching.
 * The Cendris Service will only search when all searchfields have been
 * provided.
 * 
 * The Cendris Service will try to place the resulting address information on
 * the result fields subscribed. So when the netnumber has not been subscribed,
 * the service will not set it.
 * 
 * By default the result fields will be readonly and the error field is hidden.
 *
 * 05-03-2011: Added compatibility for multiple cendris forms on one page.
 * 
 */

var cendrisService = {

  // The ids of the fields supported. A client should subscribe to the
  // cendrisService one of these fields.
  zipCodeId : 'zipcode',
  houseNumberId : 'housenumber',
  cityId : 'city',
  streetId : 'street',
  netNumberId : 'netnumber',
  errorId : 'error',

  addressSearched : null,

  cendrisAddressIds : {
    zipcode : null,
    housenumber : null,
    city : null,
    street : null,
    netnumber : null
  },
   
  cendrisForms : [], 
 
  // Creates a cendris address
  createCendrisAddressSearch : function(zipCode, houseNumber) {
    var zipCode6Digits = zipCode;
    if (zipCode && zipCode.length == 7) {
      var numericPart = zipCode.substr(0, 4);
      var alfaNumericPart = zipCode.substr(5);
      zipCode6Digits = numericPart + alfaNumericPart; 
    }     

    var cendrisAddressSearch = {
      zipCode : zipCode6Digits,
      houseNumber : houseNumber,

      equals : function(cendrisAddress) {
        return cendrisAddress && cendrisAddress.zipCode == this.zipCode && cendrisAddress.houseNumber == this.houseNumber;
      },

      isValid : function() {
        return this.zipCode && this.zipCode.length == 6 && this.houseNumber;
      }
    }
    return cendrisAddressSearch;
  },

  //adds a new form to the array and fills the first value
  addNewForm : function(cendrisId, domElementId){
    var newCendrisAddresIds = { zipcode : null,
                  housenumber : null,
                  city : null,
                  street : null,
                  netnumber : null
                  }             
    newCendrisAddresIds[cendrisId] = domElementId;
    this.cendrisForms.push(newCendrisAddresIds);
  }, 
  
  subscribeWithCendris : function(cendrisId, domElementId) {
    // create the array if it doesn't exist yet.
    if (this.cendrisForms == null) {
      this.cendrisForms = new Array();
    }
    
    // if the array is empty OR if the current id is already filled in the last form, THEN add a new form
    if ((this.cendrisForms.length == 0) || (this.cendrisForms[this.cendrisForms.length-1][cendrisId] != null)){
      this.addNewForm(cendrisId, domElementId);
    } else {
      //add the current value to the last form.
      this.cendrisForms[this.cendrisForms.length-1][cendrisId] = domElementId;
    }

    // add events and do the init stuff...  
    var domElement = $('#' + domElementId); 

    // Add a blur event handler to the search fields
    if (cendrisId == this.zipCodeId || cendrisId == this.houseNumberId) {
      domElement.blur(function() { cendrisService.searchAddress(this) });
    }
     
    // Make the city and street fields readonly when they are initialized
    if (cendrisId == this.cityId || cendrisId == this.streetId || cendrisId == this.citynetNumberId) {
      domElement.attr('readonly', 'readonly');
    }

    // Hide the error field when it's initialized
    if (cendrisId == this.errorId) {
      domElement.hide();
    }
  },  
  
  //finds the form that contains the supplied elementid
  findForm : function(elementId) {
    for (var i = 0; i <= this.cendrisForms.length; i++){
      if ((this.cendrisForms[i][this.zipCodeId] == elementId) || (this.cendrisForms[i][this.houseNumberId] == elementId)) {
        return this.cendrisForms[i];
      }
    } 
  },
  
  searchAddress : function(element) {
    //determine what form the element came from and fetch that form
    var currentForm = this.findForm(element.id);

    var zipCodeId = currentForm[this.zipCodeId];
    var houseNumberId = currentForm[this.houseNumberId];
    
    // Only search when the zipCode and houseNumber ids have been subscribed
    if (zipCodeId && houseNumberId) {
      var zipCode = $('#' + zipCodeId).val();
      var houseNumber = $('#' + houseNumberId).val();
      var cendrisAddressSearch = this.createCendrisAddressSearch(zipCode, houseNumber);

      /*
       * Only search when the address to search for is valid 
       */
      if (cendrisAddressSearch.isValid() ) {

        var cityId = currentForm[this.cityId];
        var streetId = currentForm[this.streetId];
        var netNumberId = currentForm[this.netNumberId];
        var errorId = currentForm[this.errorId];

        /*
         * When a field has not been subscribed, set the result on a dummy
         * element not attached to the DOM. This way we only fill the fields
         * provided, but without an if for every field.
         */
        var dummyElement = $('<input type="text" />');
        var cityDomElement = cityId ? $('#' + cityId) : dummyElement;
        var streetDomElement = streetId ? $('#' + streetId) : dummyElement;
        var netNumberDomElement = netNumberId ? $('#' + netNumberId) : dummyElement;
        var errorDomElement = errorId ? $('#' + errorId) : dummyElement;
  
        var cendrisRequestUrl = '/web/wcbservlet/com.gxwebmanager.solutions.cendrisservlet.servlet?ax_zip=' + zipCode
               + '&ax_hnr=' + houseNumber;
        $.getJSON(cendrisRequestUrl, function(data) {

          if (data && !data.error && data.straatnaam && data.woonplaats && data.netnummer) {
            streetDomElement.val(data.straatnaam);
            cityDomElement.val(data.woonplaats);
            netNumberDomElement.val(data.netnummer);
            // Remove the readonly attributes after the succesfull search
            streetDomElement.removeAttr('readonly');
            streetDomElement.closest("span.ie-readonly").removeClass('ie-readonly');
            cityDomElement.removeAttr('readonly');
            cityDomElement.closest("span.ie-readonly").removeClass('ie-readonly');
            errorDomElement.hide();
          } else {
            streetDomElement.val('');
            cityDomElement.val('');
            netNumberDomElement.val('');            
            //remove readonly attribute and hint: user needs to fill it
            streetDomElement.removeAttr('readonly');            
            streetDomElement.closest("span.ie-readonly").removeClass('ie-readonly');
            streetDomElement.closest("div").find("label.hint").remove();
            cityDomElement.removeAttr('readonly');
            cityDomElement.closest("span.ie-readonly").removeClass('ie-readonly');
            cityDomElement.closest("div").find("label.hint").remove();
            errorDomElement.show();
          }
                     
          // Call change blur so validation is performed, and validation messages are updated.
          streetDomElement.blur();
          streetDomElement.change();
          cityDomElement.blur();
          cityDomElement.change();
          netNumberDomElement.blur();
          netNumberDomElement.change();

          cendrisService.addressSearched = cendrisAddressSearch;
        });
      }
    }
  }

}
