/**
 * Predictive search (SOLR) Javascript functions used for the
 * EuroAlumni web application
 * (c) 2007 Euro-Alumni e.V.
 **/
 


/** 
 * Helper functions to work around the IE 
 * not supporting addEventListener
 * @param obj the object to which the listener should be
 *        attached
 * @param type the type of the event to listen to
 *        (e.g. "click", "keydown", etc.)
 * @param fn the function to add
 **/
function addEvent( obj, type, fn ) {
  if ( obj.attachEvent ) {
    obj['e'+type+fn] = fn;
    obj[type+fn] = function(){obj['e'+type+fn]( window.event );};
    obj.attachEvent( 'on'+type, obj[type+fn] );
  } else {
    obj.addEventListener( type, fn, false );
  }
}



/**
 * Constructs a new predictive search object of the 
 * specified search type. Before it can be used,
 * the userDetailsUrl and imageLinkTemplate properties
 * have to be set.
 * @param searchType the type of the search, e.g.
 *        user, joboffer, etc.
 **/ 
function PredictiveSearch( searchType ) {


  /** The type of the search **/
  this.searchType = searchType;
  
  /** The URL to use for the search service **/
  this.solrUrl = "";
  
  /** 
   * Link to jump directly to one result
   * (can be null, then it is ignored)
   **/
  this.jumpToResultUrl = null;
  
  /** Image link template **/
  this.imageLinkTemplate = "";
  
  /** 
   * The function to call on completion after setting
   * the data object 
   * If null, uses the jumpToResultUrl. 
   **/
  this.functionToCall = null;
  
  /** The data holder to set **/
  this.dataHolder = null;
 
  /** The request handler used **/
  this.requestHandler = new RequestHandler();
  
  /** The current request string **/
  this.requestString = null;
  
  /** Reference to self **/
  var _self = this;
 

  /**
   * Captures the key stroke from the search field 
   * and then dispatches correctly to either
   * field selection or to the background search
   * @param e the event (keystroke) to catch
   **/
  this.processSearchFieldKeyStroke = function ( e ) {
  
    //Try to get it for IE
    if ( !e ) {  
      e = window.event;
    }
    
    //Look for down key
    if ( e.keyCode == 40 ) {
      
      //Find the first element
      var user1 = document.getElementById( "user1" );
      if ( user1 ) {
        user1.className = "userSearchActiveUser";
        user1.focus();
        return;
      }
    }
    
    //Else do the search
    var searchInputBox = document.getElementById("searchInputBox");
    this.getResultsFromSearch( searchInputBox.value );
  };
 
 
  /**
   * Stops the event for the keypress action
   * from bubbling up
   **/
  this.stopEvent = function( e ) {
  
    //Try to get it for IE
    if ( !e ) {  
      e = window.event;
    }
    
    //Still nothing => exit here
    if ( ! e ) {
      return;
    }

    //Stop propagation
    
    //IE code
    e.cancelBubble = true;
    e.returnValue = false;

    //Mozilla code
    if ( e.stopPropagation ) {
      e.stopPropagation();
      e.preventDefault();
    }
  };
 

  /**
   * Captures the key stroke from the search field 
   * and then either moves the focus up, down or 
   * goes to the selected element (space, enter).
   * @param e the event (keystroke) to catch
   * @param position - the position of the current user field
   **/
  this.processUserFieldKeyStroke = function ( e ) {
  
    //Try to get it for IE
    if ( !e ) {  
      e = window.event;
    }
    
    //Still nothing => exit here
    if ( ! e ) {
      return;
    }

    //Stop propagation
    e.cancelBubble = true;
    e.returnValue = false;
    if ( e.stopPropagation ) {
      e.stopPropagation();
    }

    //Get the actual key pressed
    var key = e.keycode ? e.keycode : e.which;
  
    //Remove all highlightings
    _self.clearResultFieldHighlightings();
    
    //Get the id of the current field
    var position = eval( this.id.replace(/user/, "") );
    
    //Get the search input box
    var searchInputBox = document.getElementById( "searchInputBox" );
    
    //Look for down key
    if ( key == 40 ) {
      
      //Try to get the next one
      var nextUser = document.getElementById( "user"+(position+1) );
      if ( nextUser ) {
        nextUser.className = "userSearchActiveUser";
        nextUser.focus();
        return;
      } else {
        searchInputBox.focus();
        return;
      }
    }
  
    //Look for the up key
    if ( key == 38 ) {
    
      //If this is user 1, then go up to the search input box again
      if ( position < 2 ) {
        searchInputBox.focus();
        return;
      } else {
      
        //Try to get the previous one
        var previousUser = document.getElementById( "user"+(position-1) );
        if ( previousUser ) {
          previousUser.className = "userSearchActiveUser";
          previousUser.focus();
          return;
        }      
      }
    }
    
    //Space and Enter go directly to the target
    if ( (key == 32) || (key == 13) ) {
      if ( _self.functionToCall && (_self.functionToCall !== null) ) {
        this.onclick();
      } else {
        var thisLocation = window.location;
        thisLocation.href = this.href;
      }
    }
  };


  /**
   * Highlights the current element field
   **/
  this.highlightThisUserField = function() {
  
    //Clear out all highlightings
    _self.clearResultFieldHighlightings();
    
    //Set the current one
    this.className = "userSearchActiveUser";
  };


  /**
   * Clears all highlightings from the element fields
   **/
  this.clearResultFieldHighlightings = function() {
   
    for ( var t=1; t <= 5; t=t+1 ) {
      var currentUser = document.getElementById( "user"+t );
      if ( currentUser ) {
        currentUser.className = "";
      }
    }
  };


  /** 
   * Actually gets the results from the provided search
   * service
   * @param searchTerm the search term to look for
   **/
  this.getResultsFromSearch = function ( searchTerm ) {
  
    //Start from 3 letters onwards
    if ( (searchTerm === null) || (searchTerm.length < 2) ) {
      this.emptyResultsList();
      return;
    }
  
    //Reduce delimiting whitespace to one space in each location
    searchTerm = searchTerm.replace(/\s+/, " ");
  
    //If the last character is NOT a whitespace, add a wildcard
    if ( ! searchTerm.match(/\s+$/) ) {
      searchTerm = searchTerm + "*";
    } else {
      //Trim the search term
      searchTerm = searchTerm.replace(/\s+$/, "");
    }
    
    //Replace Umlauts in the search term (SOLR is not doing this correctly)
    searchTerm = searchTerm.replace(/[Öö]|oe|Oe/g, "o");
    searchTerm = searchTerm.replace(/[Üü]|ue|Ue/g, "u");
    searchTerm = searchTerm.replace(/[Ää]|ae|Ae/g, "a");
    searchTerm = searchTerm.replace(/ß/g, "ss");
  
     //Build the request variable
     this.requestString = 
       "?q="+encodeURIComponent(searchTerm)+" AND type:"+this.searchType+
       "&wt=json&indent=on&rows=5";
   
     //Send it to the server
     this.requestHandler.postGetRequest (
       this.solrUrl, 
       this.requestString, 
       this.displaySolrResults );
  };


  /**
   * Empties the list of results completely
   **/
  this.emptyResultsList = function () {
  
    //Get the list and empty it
    var currentResultsList = document.getElementById( "userSearchCurrentResultList" );
    while ( currentResultsList.childNodes.length > 0 ) {
      currentResultsList.removeChild( currentResultsList.firstChild );
    }
  };


  /**
   * Displays the results from the SOLR search
   * in an easily clickable list
   **/
  this.displaySolrResults = function () {
  
    var serverResponseText = this.serverResponseText;
  
    var rsp = eval("("+serverResponseText+")"); // use eval to parse Solr's JSON response
    
    //Switch depending on the search type
    if ( _self.searchType == "user" ) {
    
      //Get the list and empty it
      var currentResultsList = document.getElementById( "userSearchCurrentResultList" );
      _self.emptyResultsList();
      
      //Get all search results in the response
      var usersFound = rsp.response.docs;
    
      var userDatas = {};
      
      //If there are no results and the query has a wildcard, run the query again without the
      //wildcard at the end
      if ( (usersFound.length === 0) && (_self.requestString.substring( _self.requestString.length - 1) == "*") ) {
    	  
    	  _self.requestString = _self.requestString.replace( /.*\\*$/, "" );
    	  _self.requestHandler.postGetRequest (
    			  _self.solrUrl, 
    			  _self.requestString, 
    			  _self.displaySolrResults );
 	      
 	      return;
      }
      
    
      //Go through them and add them as elements
      for ( var t = 0; t < usersFound.length; t=t+1 ) {
    
        //Prepare the user data object
        var userData = new UserData();
        userData.id = usersFound[t].realID;
      
        //Build the user string
        var userFound = 
          usersFound[t].FirstName+" ";
    
        if ( usersFound[t].MiddleName ) {
          userFound = userFound+
          usersFound[t].MiddleName+" ";  
        }
    
        userFound = userFound+
          usersFound[t].Name+" ";
          
        if ( usersFound[t].MaidenName ) {
          userFound = userFound+
          "("+usersFound[t].MaidenName+") ";
        }
        
        //Set the full name
        userData.fullName = userFound.replace(/\s*$/, "");
    
        //Add the course and year
        var userCourseAndYear = "";
    
        if ( usersFound[t].IPBSCourse ) {
          userCourseAndYear = userCourseAndYear+
          usersFound[t].IPBSCourse+" ";
        }
    
        userCourseAndYear = userCourseAndYear+
          usersFound[t].GradYear+" ";
          
        userData.gradYearLink = userCourseAndYear;
        userData.imageID = usersFound[t].PictureID;
        userDatas[t] = userData;
      
        //Create a new list element with a link node
        var nextUser = document.createElement("li");
        var nextUserLink = document.createElement("a");
        nextUser.appendChild( nextUserLink );
        
        //Add the link target
        if ( _self.functionToCall && (_self.functionToCall !== null) ) {
          nextUserLink.href = "#";
          nextUserLink.onclick = function() {
            _self.dataHolder = userDatas[ eval(this.id.replace(/user/, ""))-1 ];
            _self.functionToCall();
            currentResultsList.innerHTML = "";
            return false;
          };
        } else {
          nextUserLink.href = _self.jumpToResultUrl+"?userid="+usersFound[t].id.replace(/user_/, "");
        }
        
        //Add the image (real or fake)
        var img = document.createElement("img");
        if ( usersFound[t].PictureID === 0 ) {
          img.src = _self.imageLinkTemplate.replace(/getpic\/PICREF/, "images/no_photo.png");
          img.alt = "No photo available";
        } else {
          img.src = _self.imageLinkTemplate.replace(/PICREF/, usersFound[t].PictureID+"/tnsk-userTiny-tnsk/"+usersFound[t].Name+".jpg");
        }
        nextUserLink.appendChild ( img );
    
        //Add the texts
        var userSpan = document.createElement("span");
        userSpan.className = "userSearchUserName";
        userSpan.appendChild( document.createTextNode( userFound ) );
        nextUserLink.appendChild ( userSpan );
        
        var userCourseAndYearSpan = document.createElement("span");
        userCourseAndYearSpan.className = "userSearchUserSubtitle";
        userCourseAndYearSpan.appendChild( document.createTextNode( userCourseAndYear ) );
        nextUserLink.appendChild ( userCourseAndYearSpan );
        
        //Add the on key press event
        //nextUserLink.onkeydown = _self.processUserFieldKeyStroke;
        //nextUserLink.attachEvent("onkeypress",  _self.processUserFieldKeyStroke );
        addEvent( nextUserLink, "keydown", _self.processUserFieldKeyStroke );
        nextUserLink.onkeypress = _self.stopEvent;
        nextUserLink.onmouseover = _self.highlightThisUserField;
        nextUserLink.onmouseout = _self.clearResultFieldHighlightings;
        
        //Finally an id to reach the elements quicker
        var nextUserID = "user"+(t+1);
        nextUserLink.setAttribute( "id", nextUserID );
        
        
        
        //Add the results
        currentResultsList.appendChild( nextUser );
      }
      
      //Move the list to the correct location, so the results 
      //appear directly below the input field
      var searchInputBox = document.getElementById( "searchInputBox" );
      var xPos = searchInputBox.offsetLeft;
      var yPos = searchInputBox.offsetTop + searchInputBox.offsetHeight;
      
      //For no reason known to man, IE needs to be further left
      if ( document.all ) {
        //xPos= xPos - 10;
      }
      
      currentResultsList.style.top = yPos + "px";
      //currentResultsList.style.left = xPos + "px";
      
    }
  };
  
  
  /**
   * Simple data holder object
   **/
  function UserData() {
    this.id;
    this.fullName;
    this.gradYearLink;
    this.imageID;
  };
}

