package hirondelle.web4j.security;

import java.util.logging.Logger;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import hirondelle.web4j.database.Db;
import hirondelle.web4j.database.SqlId;
import hirondelle.web4j.util.Util;
import hirondelle.web4j.database.DAOException;
import hirondelle.web4j.model.Id;

/** 
 Reads and writes the logged-in user's form-source id in the database.
 
 <P>Saves the users form-source id when the session ends.
*/
final class CsrfDAO implements HttpSessionBindingListener {

  /** Read in the SqlIds needed to read and write the form-souce id.   */
  static void init(String aReadSql, String aWriteSql){
    READ_SQL = aReadSql;
    WRITE_SQL = aWriteSql;
  }
  
  CsrfDAO(String aLoggedInUserName, Id aCurrentFormSourceId){
    fUserName = Id.from(aLoggedInUserName);  
    fCurrentSourceId = aCurrentFormSourceId;
  }

  /** This implementation does nothing.  */
  public void valueBound(HttpSessionBindingEvent aBindingEvent) {
    //do nothing
  }
  
  /** Save the user's current form-source id.    */
  public void valueUnbound(HttpSessionBindingEvent aBindingEvent) {
    saveCurrentFormSourceId();
  }
  
  /** 
   Return the form-source id for the user's immediately preceding session.
   
  <P>Returns <tt>null</tt> if there is no previous form-source id for the logged-in user.
  */
  Id fetchPreviousFormSourceId() throws DAOException {
    Id result = null;
    fLogger.fine("Fetching previous form-source id for " + Util.quote(fUserName) + ", using SqlId " + Util.quote(READ_SQL));
    result = Db.fetchValue(Id.class, getReadSql(), fUserName);
    if( result == null ) {
      fLogger.fine("No previous form-source id found for this user.");
    }
    return result;
  }
  
  // PRIVATE 

  private static String READ_SQL;
  private static String WRITE_SQL;

  /** Id is used since app may disallow using String. It's also more descriptive. */
  private final Id fUserName;
  
  /** Saved when session ends.  */
  private final Id fCurrentSourceId;
  
  private static final Logger fLogger = Util.getLogger(CsrfFilter.class);
  
  /** Called only when a session is about to end.  */
  private void saveCurrentFormSourceId()  {
    fLogger.finest("Saving current form-source id " + Util.quote(fCurrentSourceId) + ", for " + Util.quote(fUserName));
    fLogger.finest("Using SqlId " + Util.quote(getWriteSql()));
    try {
      Db.edit(getWriteSql(), fCurrentSourceId, fUserName);
    }
    catch (DAOException ex){
      fLogger.severe("Database problem encountered when attempting to save user's form-source id (when session ended).");
    }
  }
  
  private SqlId getReadSql() {
    return SqlId.fromStringId(READ_SQL);
  }
  
  private SqlId getWriteSql() {
    return SqlId.fromStringId(WRITE_SQL);
  }
}
